aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast
diff options
context:
space:
mode:
authorTSR Berry <20988865+TSRBerry@users.noreply.github.com>2023-04-08 01:22:00 +0200
committerMary <thog@protonmail.com>2023-04-27 23:51:14 +0200
commitcee712105850ac3385cd0091a923438167433f9f (patch)
tree4a5274b21d8b7f938c0d0ce18736d3f2993b11b1 /src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast
parentcd124bda587ef09668a971fa1cac1c3f0cfc9f21 (diff)
Move solution and projects to src
Diffstat (limited to 'src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast')
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ArraySubscriptingExpression.cs25
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ArrayType.cs59
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/BaseNode.cs113
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/BinaryExpression.cs41
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/BracedExpression.cs40
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/BracedRangeExpression.cs34
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/CallExpression.cs24
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/CastExpression.cs28
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ConditionalExpression.cs29
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ConversionExpression.cs24
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ConversionOperatorType.cs15
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/CtorDtorNameType.cs24
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/CtorVtableSpecialName.cs24
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/DeleteExpression.cs33
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/DtorName.cs15
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/DynamicExceptionSpec.cs16
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ElaboratedType.cs21
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/EnclosedExpression.cs25
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/EncodedFunction.cs77
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/FoldExpression.cs48
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ForwardTemplateReference.cs36
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/FunctionParameter.cs24
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/FunctionType.cs61
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/GlobalQualifiedName.cs15
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/InitListExpression.cs29
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/IntegerCastExpression.cs22
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/IntegerLiteral.cs42
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/LiteralOperator.cs16
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/LocalName.cs23
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/MemberExpression.cs25
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/NameType.cs29
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/NameTypeWithTemplateArguments.cs27
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/NestedName.cs26
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/NewExpression.cs55
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/NodeArray.cs30
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/NoexceptSpec.cs16
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PackedTemplateParameter.cs39
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PackedTemplateParameterExpansion.cs24
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ParentNode.cs17
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PointerType.cs45
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PostfixExpression.cs22
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PostfixQualifiedType.cs20
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PrefixExpression.cs22
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/QualifiedName.cs23
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/Qualifier.cs120
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ReferenceType.cs47
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/SpecialName.cs20
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/SpecialSubstitution.cs89
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/StdQualifiedName.cs15
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/TemplateArguments.cs26
-rw-r--r--src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ThrowExpression.cs20
51 files changed, 1740 insertions, 0 deletions
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ArraySubscriptingExpression.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ArraySubscriptingExpression.cs
new file mode 100644
index 00000000..5145ff7b
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ArraySubscriptingExpression.cs
@@ -0,0 +1,25 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class ArraySubscriptingExpression : BaseNode
+ {
+ private BaseNode _leftNode;
+ private BaseNode _subscript;
+
+ public ArraySubscriptingExpression(BaseNode leftNode, BaseNode subscript) : base(NodeType.ArraySubscriptingExpression)
+ {
+ _leftNode = leftNode;
+ _subscript = subscript;
+ }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ writer.Write("(");
+ _leftNode.Print(writer);
+ writer.Write(")[");
+ _subscript.Print(writer);
+ writer.Write("]");
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ArrayType.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ArrayType.cs
new file mode 100644
index 00000000..4b1041ab
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ArrayType.cs
@@ -0,0 +1,59 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class ArrayType : BaseNode
+ {
+ private BaseNode _base;
+ private BaseNode _dimensionExpression;
+ private string _dimensionString;
+
+ public ArrayType(BaseNode Base, BaseNode dimensionExpression = null) : base(NodeType.ArrayType)
+ {
+ _base = Base;
+ _dimensionExpression = dimensionExpression;
+ }
+
+ public ArrayType(BaseNode Base, string dimensionString) : base(NodeType.ArrayType)
+ {
+ _base = Base;
+ _dimensionString = dimensionString;
+ }
+
+ public override bool HasRightPart()
+ {
+ return true;
+ }
+
+ public override bool IsArray()
+ {
+ return true;
+ }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ _base.PrintLeft(writer);
+ }
+
+ public override void PrintRight(TextWriter writer)
+ {
+ // FIXME: detect if previous char was a ].
+ writer.Write(" ");
+
+ writer.Write("[");
+
+ if (_dimensionString != null)
+ {
+ writer.Write(_dimensionString);
+ }
+ else if (_dimensionExpression != null)
+ {
+ _dimensionExpression.Print(writer);
+ }
+
+ writer.Write("]");
+
+ _base.PrintRight(writer);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/BaseNode.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/BaseNode.cs
new file mode 100644
index 00000000..ca4b98f8
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/BaseNode.cs
@@ -0,0 +1,113 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public enum NodeType
+ {
+ CvQualifierType,
+ SimpleReferenceType,
+ NameType,
+ EncodedFunction,
+ NestedName,
+ SpecialName,
+ LiteralOperator,
+ NodeArray,
+ ElaboratedType,
+ PostfixQualifiedType,
+ SpecialSubstitution,
+ ExpandedSpecialSubstitution,
+ CtorDtorNameType,
+ EnclosedExpression,
+ ForwardTemplateReference,
+ NameTypeWithTemplateArguments,
+ PackedTemplateArgument,
+ TemplateArguments,
+ BooleanExpression,
+ CastExpression,
+ CallExpression,
+ IntegerCastExpression,
+ PackedTemplateParameter,
+ PackedTemplateParameterExpansion,
+ IntegerLiteral,
+ DeleteExpression,
+ MemberExpression,
+ ArraySubscriptingExpression,
+ InitListExpression,
+ PostfixExpression,
+ ConditionalExpression,
+ ThrowExpression,
+ FunctionParameter,
+ ConversionExpression,
+ BinaryExpression,
+ PrefixExpression,
+ BracedExpression,
+ BracedRangeExpression,
+ NewExpression,
+ QualifiedName,
+ StdQualifiedName,
+ DtOrName,
+ GlobalQualifiedName,
+ NoexceptSpec,
+ DynamicExceptionSpec,
+ FunctionType,
+ PointerType,
+ ReferenceType,
+ ConversionOperatorType,
+ LocalName,
+ CtorVtableSpecialName,
+ ArrayType
+ }
+
+ public abstract class BaseNode
+ {
+ public NodeType Type { get; protected set; }
+
+ public BaseNode(NodeType type)
+ {
+ Type = type;
+ }
+
+ public virtual void Print(TextWriter writer)
+ {
+ PrintLeft(writer);
+
+ if (HasRightPart())
+ {
+ PrintRight(writer);
+ }
+ }
+
+ public abstract void PrintLeft(TextWriter writer);
+
+ public virtual bool HasRightPart()
+ {
+ return false;
+ }
+
+ public virtual bool IsArray()
+ {
+ return false;
+ }
+
+ public virtual bool HasFunctions()
+ {
+ return false;
+ }
+
+ public virtual string GetName()
+ {
+ return null;
+ }
+
+ public virtual void PrintRight(TextWriter writer) {}
+
+ public override string ToString()
+ {
+ StringWriter writer = new StringWriter();
+
+ Print(writer);
+
+ return writer.ToString();
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/BinaryExpression.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/BinaryExpression.cs
new file mode 100644
index 00000000..0c492df3
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/BinaryExpression.cs
@@ -0,0 +1,41 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class BinaryExpression : BaseNode
+ {
+ private BaseNode _leftPart;
+ private string _name;
+ private BaseNode _rightPart;
+
+ public BinaryExpression(BaseNode leftPart, string name, BaseNode rightPart) : base(NodeType.BinaryExpression)
+ {
+ _leftPart = leftPart;
+ _name = name;
+ _rightPart = rightPart;
+ }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ if (_name.Equals(">"))
+ {
+ writer.Write("(");
+ }
+
+ writer.Write("(");
+ _leftPart.Print(writer);
+ writer.Write(") ");
+
+ writer.Write(_name);
+
+ writer.Write(" (");
+ _rightPart.Print(writer);
+ writer.Write(")");
+
+ if (_name.Equals(">"))
+ {
+ writer.Write(")");
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/BracedExpression.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/BracedExpression.cs
new file mode 100644
index 00000000..6b9782f5
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/BracedExpression.cs
@@ -0,0 +1,40 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class BracedExpression : BaseNode
+ {
+ private BaseNode _element;
+ private BaseNode _expression;
+ private bool _isArrayExpression;
+
+ public BracedExpression(BaseNode element, BaseNode expression, bool isArrayExpression) : base(NodeType.BracedExpression)
+ {
+ _element = element;
+ _expression = expression;
+ _isArrayExpression = isArrayExpression;
+ }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ if (_isArrayExpression)
+ {
+ writer.Write("[");
+ _element.Print(writer);
+ writer.Write("]");
+ }
+ else
+ {
+ writer.Write(".");
+ _element.Print(writer);
+ }
+
+ if (!_expression.GetType().Equals(NodeType.BracedExpression) || !_expression.GetType().Equals(NodeType.BracedRangeExpression))
+ {
+ writer.Write(" = ");
+ }
+
+ _expression.Print(writer);
+ }
+ }
+}
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/BracedRangeExpression.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/BracedRangeExpression.cs
new file mode 100644
index 00000000..802422d9
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/BracedRangeExpression.cs
@@ -0,0 +1,34 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class BracedRangeExpression : BaseNode
+ {
+ private BaseNode _firstNode;
+ private BaseNode _lastNode;
+ private BaseNode _expression;
+
+ public BracedRangeExpression(BaseNode firstNode, BaseNode lastNode, BaseNode expression) : base(NodeType.BracedRangeExpression)
+ {
+ _firstNode = firstNode;
+ _lastNode = lastNode;
+ _expression = expression;
+ }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ writer.Write("[");
+ _firstNode.Print(writer);
+ writer.Write(" ... ");
+ _lastNode.Print(writer);
+ writer.Write("]");
+
+ if (!_expression.GetType().Equals(NodeType.BracedExpression) || !_expression.GetType().Equals(NodeType.BracedRangeExpression))
+ {
+ writer.Write(" = ");
+ }
+
+ _expression.Print(writer);
+ }
+ }
+}
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/CallExpression.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/CallExpression.cs
new file mode 100644
index 00000000..8e3fc3e6
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/CallExpression.cs
@@ -0,0 +1,24 @@
+using System.Collections.Generic;
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class CallExpression : NodeArray
+ {
+ private BaseNode _callee;
+
+ public CallExpression(BaseNode callee, List<BaseNode> nodes) : base(nodes, NodeType.CallExpression)
+ {
+ _callee = callee;
+ }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ _callee.Print(writer);
+
+ writer.Write("(");
+ writer.Write(string.Join<BaseNode>(", ", Nodes.ToArray()));
+ writer.Write(")");
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/CastExpression.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/CastExpression.cs
new file mode 100644
index 00000000..1149a788
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/CastExpression.cs
@@ -0,0 +1,28 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class CastExpression : BaseNode
+ {
+ private string _kind;
+ private BaseNode _to;
+ private BaseNode _from;
+
+ public CastExpression(string kind, BaseNode to, BaseNode from) : base(NodeType.CastExpression)
+ {
+ _kind = kind;
+ _to = to;
+ _from = from;
+ }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ writer.Write(_kind);
+ writer.Write("<");
+ _to.PrintLeft(writer);
+ writer.Write(">(");
+ _from.PrintLeft(writer);
+ writer.Write(")");
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ConditionalExpression.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ConditionalExpression.cs
new file mode 100644
index 00000000..c0dd6717
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ConditionalExpression.cs
@@ -0,0 +1,29 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class ConditionalExpression : BaseNode
+ {
+ private BaseNode _thenNode;
+ private BaseNode _elseNode;
+ private BaseNode _conditionNode;
+
+ public ConditionalExpression(BaseNode conditionNode, BaseNode thenNode, BaseNode elseNode) : base(NodeType.ConditionalExpression)
+ {
+ _thenNode = thenNode;
+ _conditionNode = conditionNode;
+ _elseNode = elseNode;
+ }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ writer.Write("(");
+ _conditionNode.Print(writer);
+ writer.Write(") ? (");
+ _thenNode.Print(writer);
+ writer.Write(") : (");
+ _elseNode.Print(writer);
+ writer.Write(")");
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ConversionExpression.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ConversionExpression.cs
new file mode 100644
index 00000000..dd1f7a00
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ConversionExpression.cs
@@ -0,0 +1,24 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class ConversionExpression : BaseNode
+ {
+ private BaseNode _typeNode;
+ private BaseNode _expressions;
+
+ public ConversionExpression(BaseNode typeNode, BaseNode expressions) : base(NodeType.ConversionExpression)
+ {
+ _typeNode = typeNode;
+ _expressions = expressions;
+ }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ writer.Write("(");
+ _typeNode.Print(writer);
+ writer.Write(")(");
+ _expressions.Print(writer);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ConversionOperatorType.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ConversionOperatorType.cs
new file mode 100644
index 00000000..8a5cde86
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ConversionOperatorType.cs
@@ -0,0 +1,15 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class ConversionOperatorType : ParentNode
+ {
+ public ConversionOperatorType(BaseNode child) : base(NodeType.ConversionOperatorType, child) { }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ writer.Write("operator ");
+ Child.Print(writer);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/CtorDtorNameType.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/CtorDtorNameType.cs
new file mode 100644
index 00000000..5f458123
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/CtorDtorNameType.cs
@@ -0,0 +1,24 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class CtorDtorNameType : ParentNode
+ {
+ private bool _isDestructor;
+
+ public CtorDtorNameType(BaseNode name, bool isDestructor) : base(NodeType.CtorDtorNameType, name)
+ {
+ _isDestructor = isDestructor;
+ }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ if (_isDestructor)
+ {
+ writer.Write("~");
+ }
+
+ writer.Write(Child.GetName());
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/CtorVtableSpecialName.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/CtorVtableSpecialName.cs
new file mode 100644
index 00000000..3bb5b163
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/CtorVtableSpecialName.cs
@@ -0,0 +1,24 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class CtorVtableSpecialName : BaseNode
+ {
+ private BaseNode _firstType;
+ private BaseNode _secondType;
+
+ public CtorVtableSpecialName(BaseNode firstType, BaseNode secondType) : base(NodeType.CtorVtableSpecialName)
+ {
+ _firstType = firstType;
+ _secondType = secondType;
+ }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ writer.Write("construction vtable for ");
+ _firstType.Print(writer);
+ writer.Write("-in-");
+ _secondType.Print(writer);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/DeleteExpression.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/DeleteExpression.cs
new file mode 100644
index 00000000..14715d25
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/DeleteExpression.cs
@@ -0,0 +1,33 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class DeleteExpression : ParentNode
+ {
+ private bool _isGlobal;
+ private bool _isArrayExpression;
+
+ public DeleteExpression(BaseNode child, bool isGlobal, bool isArrayExpression) : base(NodeType.DeleteExpression, child)
+ {
+ _isGlobal = isGlobal;
+ _isArrayExpression = isArrayExpression;
+ }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ if (_isGlobal)
+ {
+ writer.Write("::");
+ }
+
+ writer.Write("delete");
+
+ if (_isArrayExpression)
+ {
+ writer.Write("[] ");
+ }
+
+ Child.Print(writer);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/DtorName.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/DtorName.cs
new file mode 100644
index 00000000..5cc4e6cf
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/DtorName.cs
@@ -0,0 +1,15 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class DtorName : ParentNode
+ {
+ public DtorName(BaseNode name) : base(NodeType.DtOrName, name) { }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ writer.Write("~");
+ Child.PrintLeft(writer);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/DynamicExceptionSpec.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/DynamicExceptionSpec.cs
new file mode 100644
index 00000000..faa91443
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/DynamicExceptionSpec.cs
@@ -0,0 +1,16 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class DynamicExceptionSpec : ParentNode
+ {
+ public DynamicExceptionSpec(BaseNode child) : base(NodeType.DynamicExceptionSpec, child) { }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ writer.Write("throw(");
+ Child.Print(writer);
+ writer.Write(")");
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ElaboratedType.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ElaboratedType.cs
new file mode 100644
index 00000000..086cd3dc
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ElaboratedType.cs
@@ -0,0 +1,21 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class ElaboratedType : ParentNode
+ {
+ private string _elaborated;
+
+ public ElaboratedType(string elaborated, BaseNode type) : base(NodeType.ElaboratedType, type)
+ {
+ _elaborated = elaborated;
+ }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ writer.Write(_elaborated);
+ writer.Write(" ");
+ Child.Print(writer);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/EnclosedExpression.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/EnclosedExpression.cs
new file mode 100644
index 00000000..b45481dd
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/EnclosedExpression.cs
@@ -0,0 +1,25 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class EnclosedExpression : BaseNode
+ {
+ private string _prefix;
+ private BaseNode _expression;
+ private string _postfix;
+
+ public EnclosedExpression(string prefix, BaseNode expression, string postfix) : base(NodeType.EnclosedExpression)
+ {
+ _prefix = prefix;
+ _expression = expression;
+ _postfix = postfix;
+ }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ writer.Write(_prefix);
+ _expression.Print(writer);
+ writer.Write(_postfix);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/EncodedFunction.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/EncodedFunction.cs
new file mode 100644
index 00000000..c7b6dab1
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/EncodedFunction.cs
@@ -0,0 +1,77 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class EncodedFunction : BaseNode
+ {
+ private BaseNode _name;
+ private BaseNode _params;
+ private BaseNode _cv;
+ private BaseNode _ref;
+ private BaseNode _attrs;
+ private BaseNode _ret;
+
+ public EncodedFunction(BaseNode name, BaseNode Params, BaseNode cv, BaseNode Ref, BaseNode attrs, BaseNode ret) : base(NodeType.NameType)
+ {
+ _name = name;
+ _params = Params;
+ _cv = cv;
+ _ref = Ref;
+ _attrs = attrs;
+ _ret = ret;
+ }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ if (_ret != null)
+ {
+ _ret.PrintLeft(writer);
+
+ if (!_ret.HasRightPart())
+ {
+ writer.Write(" ");
+ }
+ }
+
+ _name.Print(writer);
+
+ }
+
+ public override bool HasRightPart()
+ {
+ return true;
+ }
+
+ public override void PrintRight(TextWriter writer)
+ {
+ writer.Write("(");
+
+ if (_params != null)
+ {
+ _params.Print(writer);
+ }
+
+ writer.Write(")");
+
+ if (_ret != null)
+ {
+ _ret.PrintRight(writer);
+ }
+
+ if (_cv != null)
+ {
+ _cv.Print(writer);
+ }
+
+ if (_ref != null)
+ {
+ _ref.Print(writer);
+ }
+
+ if (_attrs != null)
+ {
+ _attrs.Print(writer);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/FoldExpression.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/FoldExpression.cs
new file mode 100644
index 00000000..04f7053e
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/FoldExpression.cs
@@ -0,0 +1,48 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class FoldExpression : BaseNode
+ {
+ private bool _isLeftFold;
+ private string _operatorName;
+ private BaseNode _expression;
+ private BaseNode _initializer;
+
+ public FoldExpression(bool isLeftFold, string operatorName, BaseNode expression, BaseNode initializer) : base(NodeType.FunctionParameter)
+ {
+ _isLeftFold = isLeftFold;
+ _operatorName = operatorName;
+ _expression = expression;
+ _initializer = initializer;
+ }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ writer.Write("(");
+
+ if (_isLeftFold && _initializer != null)
+ {
+ _initializer.Print(writer);
+ writer.Write(" ");
+ writer.Write(_operatorName);
+ writer.Write(" ");
+ }
+
+ writer.Write(_isLeftFold ? "... " : " ");
+ writer.Write(_operatorName);
+ writer.Write(!_isLeftFold ? " ..." : " ");
+ _expression.Print(writer);
+
+ if (!_isLeftFold && _initializer != null)
+ {
+ _initializer.Print(writer);
+ writer.Write(" ");
+ writer.Write(_operatorName);
+ writer.Write(" ");
+ }
+
+ writer.Write(")");
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ForwardTemplateReference.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ForwardTemplateReference.cs
new file mode 100644
index 00000000..1bbf6ef9
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ForwardTemplateReference.cs
@@ -0,0 +1,36 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class ForwardTemplateReference : BaseNode
+ {
+ // TODO: Compute inside the Demangler
+ public BaseNode Reference;
+ private int _index;
+
+ public ForwardTemplateReference(int index) : base(NodeType.ForwardTemplateReference)
+ {
+ _index = index;
+ }
+
+ public override string GetName()
+ {
+ return Reference.GetName();
+ }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ Reference.PrintLeft(writer);
+ }
+
+ public override void PrintRight(TextWriter writer)
+ {
+ Reference.PrintRight(writer);
+ }
+
+ public override bool HasRightPart()
+ {
+ return Reference.HasRightPart();
+ }
+ }
+}
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/FunctionParameter.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/FunctionParameter.cs
new file mode 100644
index 00000000..5654a048
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/FunctionParameter.cs
@@ -0,0 +1,24 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class FunctionParameter : BaseNode
+ {
+ private string _number;
+
+ public FunctionParameter(string number) : base(NodeType.FunctionParameter)
+ {
+ _number = number;
+ }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ writer.Write("fp ");
+
+ if (_number != null)
+ {
+ writer.Write(_number);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/FunctionType.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/FunctionType.cs
new file mode 100644
index 00000000..4ad0c9f5
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/FunctionType.cs
@@ -0,0 +1,61 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class FunctionType : BaseNode
+ {
+ private BaseNode _returnType;
+ private BaseNode _params;
+ private BaseNode _cvQualifier;
+ private SimpleReferenceType _referenceQualifier;
+ private BaseNode _exceptionSpec;
+
+ public FunctionType(BaseNode returnType, BaseNode Params, BaseNode cvQualifier, SimpleReferenceType referenceQualifier, BaseNode exceptionSpec) : base(NodeType.FunctionType)
+ {
+ _returnType = returnType;
+ _params = Params;
+ _cvQualifier = cvQualifier;
+ _referenceQualifier = referenceQualifier;
+ _exceptionSpec = exceptionSpec;
+ }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ _returnType.PrintLeft(writer);
+ writer.Write(" ");
+ }
+
+ public override void PrintRight(TextWriter writer)
+ {
+ writer.Write("(");
+ _params.Print(writer);
+ writer.Write(")");
+
+ _returnType.PrintRight(writer);
+
+ _cvQualifier.Print(writer);
+
+ if (_referenceQualifier.Qualifier != Reference.None)
+ {
+ writer.Write(" ");
+ _referenceQualifier.PrintQualifier(writer);
+ }
+
+ if (_exceptionSpec != null)
+ {
+ writer.Write(" ");
+ _exceptionSpec.Print(writer);
+ }
+ }
+
+ public override bool HasRightPart()
+ {
+ return true;
+ }
+
+ public override bool HasFunctions()
+ {
+ return true;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/GlobalQualifiedName.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/GlobalQualifiedName.cs
new file mode 100644
index 00000000..d3b6a558
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/GlobalQualifiedName.cs
@@ -0,0 +1,15 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class GlobalQualifiedName : ParentNode
+ {
+ public GlobalQualifiedName(BaseNode child) : base(NodeType.GlobalQualifiedName, child) { }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ writer.Write("::");
+ Child.Print(writer);
+ }
+ }
+}
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/InitListExpression.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/InitListExpression.cs
new file mode 100644
index 00000000..7155dd60
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/InitListExpression.cs
@@ -0,0 +1,29 @@
+using System.Collections.Generic;
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class InitListExpression : BaseNode
+ {
+ private BaseNode _typeNode;
+ private List<BaseNode> _nodes;
+
+ public InitListExpression(BaseNode typeNode, List<BaseNode> nodes) : base(NodeType.InitListExpression)
+ {
+ _typeNode = typeNode;
+ _nodes = nodes;
+ }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ if (_typeNode != null)
+ {
+ _typeNode.Print(writer);
+ }
+
+ writer.Write("{");
+ writer.Write(string.Join<BaseNode>(", ", _nodes.ToArray()));
+ writer.Write("}");
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/IntegerCastExpression.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/IntegerCastExpression.cs
new file mode 100644
index 00000000..ef07414d
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/IntegerCastExpression.cs
@@ -0,0 +1,22 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class IntegerCastExpression : ParentNode
+ {
+ private string _number;
+
+ public IntegerCastExpression(BaseNode type, string number) : base(NodeType.IntegerCastExpression, type)
+ {
+ _number = number;
+ }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ writer.Write("(");
+ Child.Print(writer);
+ writer.Write(")");
+ writer.Write(_number);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/IntegerLiteral.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/IntegerLiteral.cs
new file mode 100644
index 00000000..33752d00
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/IntegerLiteral.cs
@@ -0,0 +1,42 @@
+using System;
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class IntegerLiteral : BaseNode
+ {
+ private string _literalName;
+ private string _literalValue;
+
+ public IntegerLiteral(string literalName, string literalValue) : base(NodeType.IntegerLiteral)
+ {
+ _literalValue = literalValue;
+ _literalName = literalName;
+ }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ if (_literalName.Length > 3)
+ {
+ writer.Write("(");
+ writer.Write(_literalName);
+ writer.Write(")");
+ }
+
+ if (_literalValue[0] == 'n')
+ {
+ writer.Write("-");
+ writer.Write(_literalValue.AsSpan(1));
+ }
+ else
+ {
+ writer.Write(_literalValue);
+ }
+
+ if (_literalName.Length <= 3)
+ {
+ writer.Write(_literalName);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/LiteralOperator.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/LiteralOperator.cs
new file mode 100644
index 00000000..f7e86c9e
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/LiteralOperator.cs
@@ -0,0 +1,16 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class LiteralOperator : ParentNode
+ {
+ public LiteralOperator(BaseNode child) : base(NodeType.LiteralOperator, child) { }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ writer.Write("operator \"");
+ Child.PrintLeft(writer);
+ writer.Write("\"");
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/LocalName.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/LocalName.cs
new file mode 100644
index 00000000..15d46b38
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/LocalName.cs
@@ -0,0 +1,23 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class LocalName : BaseNode
+ {
+ private BaseNode _encoding;
+ private BaseNode _entity;
+
+ public LocalName(BaseNode encoding, BaseNode entity) : base(NodeType.LocalName)
+ {
+ _encoding = encoding;
+ _entity = entity;
+ }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ _encoding.Print(writer);
+ writer.Write("::");
+ _entity.Print(writer);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/MemberExpression.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/MemberExpression.cs
new file mode 100644
index 00000000..9b91f6f5
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/MemberExpression.cs
@@ -0,0 +1,25 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class MemberExpression : BaseNode
+ {
+ private BaseNode _leftNode;
+ private string _kind;
+ private BaseNode _rightNode;
+
+ public MemberExpression(BaseNode leftNode, string kind, BaseNode rightNode) : base(NodeType.MemberExpression)
+ {
+ _leftNode = leftNode;
+ _kind = kind;
+ _rightNode = rightNode;
+ }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ _leftNode.Print(writer);
+ writer.Write(_kind);
+ _rightNode.Print(writer);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/NameType.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/NameType.cs
new file mode 100644
index 00000000..f9f4cb20
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/NameType.cs
@@ -0,0 +1,29 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class NameType : BaseNode
+ {
+ private string _nameValue;
+
+ public NameType(string nameValue, NodeType type) : base(type)
+ {
+ _nameValue = nameValue;
+ }
+
+ public NameType(string nameValue) : base(NodeType.NameType)
+ {
+ _nameValue = nameValue;
+ }
+
+ public override string GetName()
+ {
+ return _nameValue;
+ }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ writer.Write(_nameValue);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/NameTypeWithTemplateArguments.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/NameTypeWithTemplateArguments.cs
new file mode 100644
index 00000000..ee725f36
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/NameTypeWithTemplateArguments.cs
@@ -0,0 +1,27 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class NameTypeWithTemplateArguments : BaseNode
+ {
+ private BaseNode _prev;
+ private BaseNode _templateArgument;
+
+ public NameTypeWithTemplateArguments(BaseNode prev, BaseNode templateArgument) : base(NodeType.NameTypeWithTemplateArguments)
+ {
+ _prev = prev;
+ _templateArgument = templateArgument;
+ }
+
+ public override string GetName()
+ {
+ return _prev.GetName();
+ }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ _prev.Print(writer);
+ _templateArgument.Print(writer);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/NestedName.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/NestedName.cs
new file mode 100644
index 00000000..640c200c
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/NestedName.cs
@@ -0,0 +1,26 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class NestedName : ParentNode
+ {
+ private BaseNode _name;
+
+ public NestedName(BaseNode name, BaseNode type) : base(NodeType.NestedName, type)
+ {
+ _name = name;
+ }
+
+ public override string GetName()
+ {
+ return _name.GetName();
+ }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ Child.Print(writer);
+ writer.Write("::");
+ _name.Print(writer);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/NewExpression.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/NewExpression.cs
new file mode 100644
index 00000000..ba4690af
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/NewExpression.cs
@@ -0,0 +1,55 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class NewExpression : BaseNode
+ {
+ private NodeArray _expressions;
+ private BaseNode _typeNode;
+ private NodeArray _initializers;
+
+ private bool _isGlobal;
+ private bool _isArrayExpression;
+
+ public NewExpression(NodeArray expressions, BaseNode typeNode, NodeArray initializers, bool isGlobal, bool isArrayExpression) : base(NodeType.NewExpression)
+ {
+ _expressions = expressions;
+ _typeNode = typeNode;
+ _initializers = initializers;
+
+ _isGlobal = isGlobal;
+ _isArrayExpression = isArrayExpression;
+ }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ if (_isGlobal)
+ {
+ writer.Write("::operator ");
+ }
+
+ writer.Write("new ");
+
+ if (_isArrayExpression)
+ {
+ writer.Write("[] ");
+ }
+
+ if (_expressions.Nodes.Count != 0)
+ {
+ writer.Write("(");
+ _expressions.Print(writer);
+ writer.Write(")");
+ }
+
+ _typeNode.Print(writer);
+
+ if (_initializers.Nodes.Count != 0)
+ {
+ writer.Write("(");
+ _initializers.Print(writer);
+ writer.Write(")");
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/NodeArray.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/NodeArray.cs
new file mode 100644
index 00000000..1482dfc3
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/NodeArray.cs
@@ -0,0 +1,30 @@
+using System.Collections.Generic;
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class NodeArray : BaseNode
+ {
+ public List<BaseNode> Nodes { get; protected set; }
+
+ public NodeArray(List<BaseNode> nodes) : base(NodeType.NodeArray)
+ {
+ Nodes = nodes;
+ }
+
+ public NodeArray(List<BaseNode> nodes, NodeType type) : base(type)
+ {
+ Nodes = nodes;
+ }
+
+ public override bool IsArray()
+ {
+ return true;
+ }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ writer.Write(string.Join<BaseNode>(", ", Nodes.ToArray()));
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/NoexceptSpec.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/NoexceptSpec.cs
new file mode 100644
index 00000000..49044493
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/NoexceptSpec.cs
@@ -0,0 +1,16 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class NoexceptSpec : ParentNode
+ {
+ public NoexceptSpec(BaseNode child) : base(NodeType.NoexceptSpec, child) { }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ writer.Write("noexcept(");
+ Child.Print(writer);
+ writer.Write(")");
+ }
+ }
+}
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PackedTemplateParameter.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PackedTemplateParameter.cs
new file mode 100644
index 00000000..4c820095
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PackedTemplateParameter.cs
@@ -0,0 +1,39 @@
+using System.Collections.Generic;
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class PackedTemplateParameter : NodeArray
+ {
+ public PackedTemplateParameter(List<BaseNode> nodes) : base(nodes, NodeType.PackedTemplateParameter) { }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ foreach (BaseNode node in Nodes)
+ {
+ node.PrintLeft(writer);
+ }
+ }
+
+ public override void PrintRight(TextWriter writer)
+ {
+ foreach (BaseNode node in Nodes)
+ {
+ node.PrintLeft(writer);
+ }
+ }
+
+ public override bool HasRightPart()
+ {
+ foreach (BaseNode node in Nodes)
+ {
+ if (node.HasRightPart())
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PackedTemplateParameterExpansion.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PackedTemplateParameterExpansion.cs
new file mode 100644
index 00000000..c3645044
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PackedTemplateParameterExpansion.cs
@@ -0,0 +1,24 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class PackedTemplateParameterExpansion : ParentNode
+ {
+ public PackedTemplateParameterExpansion(BaseNode child) : base(NodeType.PackedTemplateParameterExpansion, child) {}
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ if (Child is PackedTemplateParameter)
+ {
+ if (((PackedTemplateParameter)Child).Nodes.Count != 0)
+ {
+ Child.Print(writer);
+ }
+ }
+ else
+ {
+ writer.Write("...");
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ParentNode.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ParentNode.cs
new file mode 100644
index 00000000..786abced
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ParentNode.cs
@@ -0,0 +1,17 @@
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public abstract class ParentNode : BaseNode
+ {
+ public BaseNode Child { get; private set; }
+
+ public ParentNode(NodeType type, BaseNode child) : base(type)
+ {
+ Child = child;
+ }
+
+ public override string GetName()
+ {
+ return Child.GetName();
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PointerType.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PointerType.cs
new file mode 100644
index 00000000..b1a3ec42
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PointerType.cs
@@ -0,0 +1,45 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class PointerType : BaseNode
+ {
+ private BaseNode _child;
+
+ public PointerType(BaseNode child) : base(NodeType.PointerType)
+ {
+ _child = child;
+ }
+
+ public override bool HasRightPart()
+ {
+ return _child.HasRightPart();
+ }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ _child.PrintLeft(writer);
+ if (_child.IsArray())
+ {
+ writer.Write(" ");
+ }
+
+ if (_child.IsArray() || _child.HasFunctions())
+ {
+ writer.Write("(");
+ }
+
+ writer.Write("*");
+ }
+
+ public override void PrintRight(TextWriter writer)
+ {
+ if (_child.IsArray() || _child.HasFunctions())
+ {
+ writer.Write(")");
+ }
+
+ _child.PrintRight(writer);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PostfixExpression.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PostfixExpression.cs
new file mode 100644
index 00000000..ccaea3ba
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PostfixExpression.cs
@@ -0,0 +1,22 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class PostfixExpression : ParentNode
+ {
+ private string _operator;
+
+ public PostfixExpression(BaseNode type, string Operator) : base(NodeType.PostfixExpression, type)
+ {
+ _operator = Operator;
+ }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ writer.Write("(");
+ Child.Print(writer);
+ writer.Write(")");
+ writer.Write(_operator);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PostfixQualifiedType.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PostfixQualifiedType.cs
new file mode 100644
index 00000000..5024a8f9
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PostfixQualifiedType.cs
@@ -0,0 +1,20 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class PostfixQualifiedType : ParentNode
+ {
+ private string _postfixQualifier;
+
+ public PostfixQualifiedType(string postfixQualifier, BaseNode type) : base(NodeType.PostfixQualifiedType, type)
+ {
+ _postfixQualifier = postfixQualifier;
+ }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ Child.Print(writer);
+ writer.Write(_postfixQualifier);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PrefixExpression.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PrefixExpression.cs
new file mode 100644
index 00000000..9c3d4552
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PrefixExpression.cs
@@ -0,0 +1,22 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class PrefixExpression : ParentNode
+ {
+ private string _prefix;
+
+ public PrefixExpression(string prefix, BaseNode child) : base(NodeType.PrefixExpression, child)
+ {
+ _prefix = prefix;
+ }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ writer.Write(_prefix);
+ writer.Write("(");
+ Child.Print(writer);
+ writer.Write(")");
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/QualifiedName.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/QualifiedName.cs
new file mode 100644
index 00000000..2e18f564
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/QualifiedName.cs
@@ -0,0 +1,23 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class QualifiedName : BaseNode
+ {
+ private BaseNode _qualifier;
+ private BaseNode _name;
+
+ public QualifiedName(BaseNode qualifier, BaseNode name) : base(NodeType.QualifiedName)
+ {
+ _qualifier = qualifier;
+ _name = name;
+ }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ _qualifier.Print(writer);
+ writer.Write("::");
+ _name.Print(writer);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/Qualifier.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/Qualifier.cs
new file mode 100644
index 00000000..cb6dd6bf
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/Qualifier.cs
@@ -0,0 +1,120 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public enum Cv
+ {
+ None,
+ Const,
+ Volatile,
+ Restricted = 4
+ }
+
+ public enum Reference
+ {
+ None,
+ RValue,
+ LValue
+ }
+
+ public class CvType : ParentNode
+ {
+ public Cv Qualifier;
+
+ public CvType(Cv qualifier, BaseNode child) : base(NodeType.CvQualifierType, child)
+ {
+ Qualifier = qualifier;
+ }
+
+ public void PrintQualifier(TextWriter writer)
+ {
+ if ((Qualifier & Cv.Const) != 0)
+ {
+ writer.Write(" const");
+ }
+
+ if ((Qualifier & Cv.Volatile) != 0)
+ {
+ writer.Write(" volatile");
+ }
+
+ if ((Qualifier & Cv.Restricted) != 0)
+ {
+ writer.Write(" restrict");
+ }
+ }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ if (Child != null)
+ {
+ Child.PrintLeft(writer);
+ }
+
+ PrintQualifier(writer);
+ }
+
+ public override bool HasRightPart()
+ {
+ return Child != null && Child.HasRightPart();
+ }
+
+ public override void PrintRight(TextWriter writer)
+ {
+ if (Child != null)
+ {
+ Child.PrintRight(writer);
+ }
+ }
+ }
+
+ public class SimpleReferenceType : ParentNode
+ {
+ public Reference Qualifier;
+
+ public SimpleReferenceType(Reference qualifier, BaseNode child) : base(NodeType.SimpleReferenceType, child)
+ {
+ Qualifier = qualifier;
+ }
+
+ public void PrintQualifier(TextWriter writer)
+ {
+ if ((Qualifier & Reference.LValue) != 0)
+ {
+ writer.Write("&");
+ }
+
+ if ((Qualifier & Reference.RValue) != 0)
+ {
+ writer.Write("&&");
+ }
+ }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ if (Child != null)
+ {
+ Child.PrintLeft(writer);
+ }
+ else if (Qualifier != Reference.None)
+ {
+ writer.Write(" ");
+ }
+
+ PrintQualifier(writer);
+ }
+
+ public override bool HasRightPart()
+ {
+ return Child != null && Child.HasRightPart();
+ }
+
+ public override void PrintRight(TextWriter writer)
+ {
+ if (Child != null)
+ {
+ Child.PrintRight(writer);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ReferenceType.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ReferenceType.cs
new file mode 100644
index 00000000..a3214171
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ReferenceType.cs
@@ -0,0 +1,47 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class ReferenceType : BaseNode
+ {
+ private string _reference;
+ private BaseNode _child;
+
+ public ReferenceType(string reference, BaseNode child) : base(NodeType.ReferenceType)
+ {
+ _reference = reference;
+ _child = child;
+ }
+
+ public override bool HasRightPart()
+ {
+ return _child.HasRightPart();
+ }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ _child.PrintLeft(writer);
+
+ if (_child.IsArray())
+ {
+ writer.Write(" ");
+ }
+
+ if (_child.IsArray() || _child.HasFunctions())
+ {
+ writer.Write("(");
+ }
+
+ writer.Write(_reference);
+ }
+ public override void PrintRight(TextWriter writer)
+ {
+ if (_child.IsArray() || _child.HasFunctions())
+ {
+ writer.Write(")");
+ }
+
+ _child.PrintRight(writer);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/SpecialName.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/SpecialName.cs
new file mode 100644
index 00000000..1447458b
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/SpecialName.cs
@@ -0,0 +1,20 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class SpecialName : ParentNode
+ {
+ private string _specialValue;
+
+ public SpecialName(string specialValue, BaseNode type) : base(NodeType.SpecialName, type)
+ {
+ _specialValue = specialValue;
+ }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ writer.Write(_specialValue);
+ Child.Print(writer);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/SpecialSubstitution.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/SpecialSubstitution.cs
new file mode 100644
index 00000000..8d45e180
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/SpecialSubstitution.cs
@@ -0,0 +1,89 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class SpecialSubstitution : BaseNode
+ {
+ public enum SpecialType
+ {
+ Allocator,
+ BasicString,
+ String,
+ IStream,
+ OStream,
+ IOStream
+ }
+
+ private SpecialType _specialSubstitutionKey;
+
+ public SpecialSubstitution(SpecialType specialSubstitutionKey) : base(NodeType.SpecialSubstitution)
+ {
+ _specialSubstitutionKey = specialSubstitutionKey;
+ }
+
+ public void SetExtended()
+ {
+ Type = NodeType.ExpandedSpecialSubstitution;
+ }
+
+ public override string GetName()
+ {
+ switch (_specialSubstitutionKey)
+ {
+ case SpecialType.Allocator:
+ return "allocator";
+ case SpecialType.BasicString:
+ return "basic_string";
+ case SpecialType.String:
+ if (Type == NodeType.ExpandedSpecialSubstitution)
+ {
+ return "basic_string";
+ }
+
+ return "string";
+ case SpecialType.IStream:
+ return "istream";
+ case SpecialType.OStream:
+ return "ostream";
+ case SpecialType.IOStream:
+ return "iostream";
+ }
+
+ return null;
+ }
+
+ private string GetExtendedName()
+ {
+ switch (_specialSubstitutionKey)
+ {
+ case SpecialType.Allocator:
+ return "std::allocator";
+ case SpecialType.BasicString:
+ return "std::basic_string";
+ case SpecialType.String:
+ return "std::basic_string<char, std::char_traits<char>, std::allocator<char> >";
+ case SpecialType.IStream:
+ return "std::basic_istream<char, std::char_traits<char> >";
+ case SpecialType.OStream:
+ return "std::basic_ostream<char, std::char_traits<char> >";
+ case SpecialType.IOStream:
+ return "std::basic_iostream<char, std::char_traits<char> >";
+ }
+
+ return null;
+ }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ if (Type == NodeType.ExpandedSpecialSubstitution)
+ {
+ writer.Write(GetExtendedName());
+ }
+ else
+ {
+ writer.Write("std::");
+ writer.Write(GetName());
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/StdQualifiedName.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/StdQualifiedName.cs
new file mode 100644
index 00000000..c3a97d60
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/StdQualifiedName.cs
@@ -0,0 +1,15 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class StdQualifiedName : ParentNode
+ {
+ public StdQualifiedName(BaseNode child) : base(NodeType.StdQualifiedName, child) { }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ writer.Write("std::");
+ Child.Print(writer);
+ }
+ }
+}
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/TemplateArguments.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/TemplateArguments.cs
new file mode 100644
index 00000000..aefd668d
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/TemplateArguments.cs
@@ -0,0 +1,26 @@
+using System.Collections.Generic;
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class TemplateArguments : NodeArray
+ {
+ public TemplateArguments(List<BaseNode> nodes) : base(nodes, NodeType.TemplateArguments) { }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ string Params = string.Join<BaseNode>(", ", Nodes.ToArray());
+
+ writer.Write("<");
+
+ writer.Write(Params);
+
+ if (Params.EndsWith(">"))
+ {
+ writer.Write(" ");
+ }
+
+ writer.Write(">");
+ }
+ }
+}
diff --git a/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ThrowExpression.cs b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ThrowExpression.cs
new file mode 100644
index 00000000..2972a31c
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ThrowExpression.cs
@@ -0,0 +1,20 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast
+{
+ public class ThrowExpression : BaseNode
+ {
+ private BaseNode _expression;
+
+ public ThrowExpression(BaseNode expression) : base(NodeType.ThrowExpression)
+ {
+ _expression = expression;
+ }
+
+ public override void PrintLeft(TextWriter writer)
+ {
+ writer.Write("throw ");
+ _expression.Print(writer);
+ }
+ }
+} \ No newline at end of file