Skip to content

Commit 9ae5236

Browse files
ParserPrep (#88)
1 parent d416634 commit 9ae5236

18 files changed

Lines changed: 836 additions & 200 deletions

RDCore.Parsing/AST/DeclarationsParseTreeListener.cs

Lines changed: 371 additions & 0 deletions
Large diffs are not rendered by default.

RDCore.Parsing/AST/ModuleParseTreeListener.cs

Lines changed: 0 additions & 153 deletions
This file was deleted.

RDCore.Parsing/AST/NodeBuilder.cs

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
using RDCore.Parsing.Syntax;
2+
using RDCore.SDK.Model;
3+
using RDCore.SDK.Model.AST.Abstract;
4+
using RDCore.SDK.Model.AST.Declarations;
5+
using RDCore.SDK.Model.AST.Directives;
6+
7+
namespace RDCore.Parsing.AST;
8+
9+
internal class NodeBuilder(Uri rootUri, string? nodeId = null)
10+
{
11+
private readonly Uri _rootUri = rootUri;
12+
private readonly List<BoundNode> _children = [];
13+
14+
public void AddChild(BoundNode node) => _children.Add(node);
15+
public void UpdateLastChild(BoundNode node)
16+
{
17+
if (node.GetType() != _children.Last().GetType())
18+
{
19+
// that would be an arbitrary replacement, most likely a bug.
20+
throw new InvalidOperationException();
21+
}
22+
_children.RemoveAt(_children.Count - 1);
23+
_children.Add(node);
24+
}
25+
26+
public IEnumerable<BoundNode> GetChildren => _children.AsEnumerable();
27+
public BoundNode BuildAttributeDirective(VBAParser.AttributeStmtContext context)
28+
{
29+
// name may be qualified
30+
var identifiers = context.attributeName().GetText().Split('.');
31+
var name = identifiers.Length == 1 ? identifiers[0] : identifiers.Last();
32+
var qualifier = identifiers.Length == 2 ? identifiers[0] : null;
33+
return new AttributeDirectiveNode(
34+
GetUriWithFragmentFor($"{(qualifier is not null ? $"{qualifier}." : string.Empty)}{name}"),
35+
context.GetSourceLocation(_rootUri),
36+
name,
37+
_children[0],
38+
qualifier);
39+
}
40+
public BoundNode BuildImplementsDirective(VBAParser.ImplementsStmtContext context)
41+
{
42+
var name = context.expression().GetText().Split('.').Last(); // MS-VBAL: <class-type-name> (may be qualified)
43+
return new ImplementsDirectiveNode(
44+
GetUriWithFragmentFor($"implements-{name}"),
45+
context.GetSourceLocation(_rootUri),
46+
(BoundExpression)_children[0]);
47+
}
48+
public BoundNode BuildExternalDeclaration(VBAParser.DeclareStmtContext context)
49+
{
50+
var name = context.identifier().untypedIdentifier()?.GetText()
51+
?? context.identifier().typedIdentifier().untypedIdentifier().GetText();
52+
var visibility = context.visibility()?.GetText();
53+
var kind = context.FUNCTION() is not null ? MemberKind.ExternalFunction : MemberKind.ExternalProcedure;
54+
var isPtrSafe = context.PTRSAFE() is not null;
55+
var literals = context.STRINGLITERAL();
56+
var lib = literals[0].GetText();
57+
var alias = literals.Length > 1 ? literals[1].GetText() : null;
58+
59+
var location = context.GetSourceLocation(_rootUri);
60+
var modifier = string.IsNullOrWhiteSpace(visibility)
61+
? AccessModifier.Implicit
62+
: Enum.Parse<AccessModifier>(visibility, ignoreCase: true);
63+
64+
return new ExternalMemberDeclarationNode(
65+
GetUriWithFragmentFor(name),
66+
location,
67+
[.. _children],
68+
name,
69+
lib,
70+
isPtrSafe,
71+
kind,
72+
alias,
73+
modifier);
74+
}
75+
public BoundNode BuildEventDeclaration(VBAParser.EventStmtContext context)
76+
{
77+
var name = context.identifier().untypedIdentifier()?.GetText()
78+
?? context.identifier().typedIdentifier().untypedIdentifier().GetText();
79+
var modifier = context.visibility()?.GetText() is string value
80+
? Enum.Parse<AccessModifier>(value) : AccessModifier.Implicit;
81+
82+
return new MemberDeclarationNode(
83+
GetUriWithFragmentFor($"{Tokens.Event}_{name}"),
84+
context.GetSourceLocation(_rootUri),
85+
[.. _children],
86+
name,
87+
MemberKind.Event,
88+
modifier);
89+
}
90+
public BoundNode BuildUserDefinedTypeDeclaration(VBAParser.UdtDeclarationContext context)
91+
{
92+
var name = context.untypedIdentifier().GetText();
93+
var modifier = context.visibility()?.GetText() is string value
94+
? Enum.Parse<AccessModifier>(value) : AccessModifier.Implicit;
95+
96+
return new MemberDeclarationNode(
97+
GetUriWithFragmentFor($"{Tokens.Type}_{name}"),
98+
context.GetSourceLocation(_rootUri),
99+
[.. _children],
100+
name,
101+
MemberKind.UserDefinedType,
102+
modifier);
103+
}
104+
public BoundNode BuildEnumDeclaration(VBAParser.EnumerationStmtContext context)
105+
{
106+
var name = context.identifier().untypedIdentifier()?.GetText()
107+
?? context.identifier().typedIdentifier().untypedIdentifier().GetText();
108+
109+
var modifier = context.visibility()?.GetText() is string value
110+
? Enum.Parse<AccessModifier>(value) : AccessModifier.Implicit;
111+
112+
return new MemberDeclarationNode(
113+
GetUriWithFragmentFor($"{Tokens.Enum}_{name}"),
114+
context.GetSourceLocation(_rootUri),
115+
[.. _children],
116+
name,
117+
MemberKind.Enum,
118+
modifier);
119+
}
120+
public BoundNode BuildParameterDeclaration(VBAParser.ArgContext context, bool isPropertyWriterMember = false, bool isLast = false)
121+
{
122+
var name = context.unrestrictedIdentifier().identifier().untypedIdentifier()?.GetText()
123+
?? context.unrestrictedIdentifier().identifier().typedIdentifier().GetText();
124+
125+
var kind = context.BYVAL() is not null ? ParameterKind.ExplicitByVal
126+
: context.BYREF() is not null ? ParameterKind.ExplicitByRef
127+
: isPropertyWriterMember && isLast
128+
? ParameterKind.ImplicitByVal
129+
: ParameterKind.ImplicitByRef;
130+
131+
return new ParameterDeclarationNode(
132+
GetUriWithFragmentFor($"parameter_{name}"),
133+
context.GetSourceLocation(_rootUri),
134+
name,
135+
kind,
136+
context.OPTIONAL() is not null,
137+
context.PARAMARRAY() is not null,
138+
[.. _children]);
139+
}
140+
public BoundNode BuildPropertyGetDeclaration(VBAParser.PropertyGetStmtContext context)
141+
{
142+
var name = context.functionName().identifier().untypedIdentifier()?.GetText()
143+
?? context.functionName().identifier().typedIdentifier().untypedIdentifier().GetText();
144+
145+
var modifier = context.visibility()?.GetText() is string value
146+
? Enum.Parse<AccessModifier>(value) : AccessModifier.Implicit;
147+
148+
return new MemberDeclarationNode(
149+
GetUriWithFragmentFor($"get_{name}"),
150+
context.GetSourceLocation(_rootUri),
151+
[.. _children],
152+
name,
153+
MemberKind.PropertyGet,
154+
modifier);
155+
}
156+
public BoundNode BuildPropertyLetDeclaration(VBAParser.PropertyLetStmtContext context)
157+
{
158+
var name = context.subroutineName().identifier().untypedIdentifier()?.GetText()
159+
?? context.subroutineName().identifier().typedIdentifier().untypedIdentifier().GetText();
160+
161+
var modifier = context.visibility()?.GetText() is string value
162+
? Enum.Parse<AccessModifier>(value) : AccessModifier.Implicit;
163+
164+
return new MemberDeclarationNode(
165+
GetUriWithFragmentFor($"let_{name}"),
166+
context.GetSourceLocation(_rootUri),
167+
[.. _children],
168+
name,
169+
MemberKind.PropertyLet,
170+
modifier);
171+
}
172+
public BoundNode BuildPropertySetDeclaration(VBAParser.PropertySetStmtContext context)
173+
{
174+
var name = context.subroutineName().identifier().untypedIdentifier()?.GetText()
175+
?? context.subroutineName().identifier().typedIdentifier().untypedIdentifier().GetText();
176+
177+
var modifier = context.visibility()?.GetText() is string value
178+
? Enum.Parse<AccessModifier>(value) : AccessModifier.Implicit;
179+
180+
return new MemberDeclarationNode(
181+
GetUriWithFragmentFor($"set_{name}"),
182+
context.GetSourceLocation(_rootUri),
183+
[.. _children],
184+
name,
185+
MemberKind.PropertySet,
186+
modifier);
187+
}
188+
public BoundNode BuildProcedureDeclaration(VBAParser.SubStmtContext context)
189+
{
190+
var name = context.subroutineName().identifier().untypedIdentifier()?.GetText()
191+
?? context.subroutineName().identifier().typedIdentifier().untypedIdentifier().GetText();
192+
193+
var modifier = context.visibility()?.GetText() is string value
194+
? Enum.Parse<AccessModifier>(value) : AccessModifier.Implicit;
195+
196+
return new MemberDeclarationNode(
197+
GetUriWithFragmentFor($"{Tokens.Sub}_{name}"),
198+
context.GetSourceLocation(_rootUri),
199+
[.. _children],
200+
name,
201+
MemberKind.Procedure,
202+
modifier);
203+
}
204+
public BoundNode BuildFunctionDeclaration(VBAParser.FunctionStmtContext context)
205+
{
206+
var name = context.functionName().identifier().untypedIdentifier()?.GetText()
207+
?? context.functionName().identifier().typedIdentifier().untypedIdentifier().GetText();
208+
209+
var modifier = context.visibility()?.GetText() is string value
210+
? Enum.Parse<AccessModifier>(value) : AccessModifier.Implicit;
211+
212+
return new MemberDeclarationNode(
213+
GetUriWithFragmentFor($"{Tokens.Function}_{name}"),
214+
context.GetSourceLocation(_rootUri),
215+
[.. _children],
216+
name,
217+
MemberKind.Function,
218+
modifier);
219+
}
220+
private Uri GetUriWithFragmentFor(string name) => new($"{_rootUri.AbsolutePath.TrimEnd('#')}{(nodeId is not null ? $"/{nodeId}#" : "#")}{name.ToLowerInvariant()}");
221+
}

RDCore.Runtime/Semantics/Abstract/RuntimeSemantics.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,5 +71,5 @@ protected virtual RuntimeSemanticsEvaluationResult EvaluateSemanticResult(ISymbo
7171
/// A helper method to get a <c>VBRuntimeErrorInfo</c> error metadata from derived types as needed.
7272
/// </summary>
7373
protected static VBRuntimeErrorInfo OnRuntimeError(VBRuntimeErrorId errorId, BoundNode node, string verbose)
74-
=> VBRuntimeErrorInfo.For(errorId, node.Location, verbose);
74+
=> VBRuntimeErrorInfo.For(errorId, node.SourceLocation, verbose);
7575
}
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using RDCore.SDK.Model.Source;
2+
using System.Collections.Immutable;
23

34
namespace RDCore.SDK.Model.AST.Abstract;
45

@@ -8,5 +9,5 @@ namespace RDCore.SDK.Model.AST.Abstract;
89
/// </summary>
910
/// <param name="SemanticId">A semantic <c>Uri</c> uniquely identifying this specific node.</param>
1011
/// <param name="Location">The document location (<c>Uri</c>+<c>Range</c>) of the bound expression.</param>
11-
public abstract record class BoundDirective(Uri SemanticId, SourceLocation Location)
12-
: BoundNode(SemanticId, Location, []);
12+
public abstract record class BoundDirective(Uri SemanticId, SourceLocation Location, ImmutableArray<BoundNode> Children)
13+
: BoundNode(SemanticId, Location, Children);

0 commit comments

Comments
 (0)