Skip to content

Commit 9384df7

Browse files
author
Минин Степан Александрович
committed
refactor(code structure): TopDownParser
Split `TopDownParser` into separate files for better modularity and maintainability. Added implementations for expressions, declarations, and statements handling.
1 parent 94e226a commit 9384df7

4 files changed

Lines changed: 825 additions & 800 deletions

File tree

Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
using HydraScript.Domain.FrontEnd.Parser.Impl.Ast.Nodes;
2+
using HydraScript.Domain.FrontEnd.Parser.Impl.Ast.Nodes.Declarations;
3+
using HydraScript.Domain.FrontEnd.Parser.Impl.Ast.Nodes.Declarations.AfterTypesAreLoaded;
4+
using HydraScript.Domain.FrontEnd.Parser.Impl.Ast.Nodes.Expressions;
5+
using HydraScript.Domain.FrontEnd.Parser.Impl.Ast.Nodes.Expressions.PrimaryExpressions;
6+
7+
namespace HydraScript.Domain.FrontEnd.Parser.Impl;
8+
9+
public partial class TopDownParser
10+
{
11+
/// <summary>
12+
/// Declaration -> LexicalDeclaration
13+
/// FunctionDeclaration
14+
/// TypeDeclaration
15+
/// </summary>
16+
private Declaration Declaration()
17+
{
18+
if (CurrentIsKeyword("function"))
19+
{
20+
return FunctionDeclaration();
21+
}
22+
23+
if (CurrentIsKeyword("let") || CurrentIsKeyword("const"))
24+
{
25+
return LexicalDeclaration();
26+
}
27+
28+
if (CurrentIsKeyword("type"))
29+
{
30+
return TypeDeclaration();
31+
}
32+
33+
return null!;
34+
}
35+
36+
/// <summary>
37+
/// FunctionDeclaration -> 'function' "Ident" '(' FunctionParameters? ')' Type? BlockStatement
38+
/// </summary>
39+
private FunctionDeclaration FunctionDeclaration()
40+
{
41+
Expect("Keyword", "function");
42+
var ident = Expect("Ident");
43+
44+
Expect("LeftParen");
45+
var args = new List<IFunctionArgument>();
46+
var indexOfFirstDefaultArgument = int.MaxValue;
47+
while (CurrentIs("Ident"))
48+
{
49+
var arg = Expect("Ident").Value;
50+
if (CurrentIs("Colon"))
51+
{
52+
Expect("Colon");
53+
var type = TypeValue();
54+
args.Add(new NamedArgument(arg, type));
55+
}
56+
else if (CurrentIs("Assign"))
57+
{
58+
Expect("Assign");
59+
var value = LiteralNode();
60+
indexOfFirstDefaultArgument = args.Count < indexOfFirstDefaultArgument
61+
? args.Count
62+
: indexOfFirstDefaultArgument;
63+
args.Add(new DefaultValueArgument(arg, value));
64+
}
65+
66+
if (!CurrentIs("RightParen"))
67+
Expect("Comma");
68+
}
69+
70+
var rp = Expect("RightParen");
71+
72+
TypeValue returnType = new TypeIdentValue(
73+
TypeId: new IdentifierReference(name: "undefined")
74+
{ Segment = rp.Segment });
75+
76+
if (CurrentIs("Colon"))
77+
{
78+
Expect("Colon");
79+
returnType = TypeValue();
80+
}
81+
82+
var name = new IdentifierReference(ident.Value) { Segment = ident.Segment };
83+
return new FunctionDeclaration(name, returnType, args, BlockStatement(), indexOfFirstDefaultArgument)
84+
{ Segment = ident.Segment };
85+
}
86+
87+
/// <summary>
88+
/// LexicalDeclaration -> LetOrConst "Ident" Initialization (',' "Ident" Initialization)*
89+
/// </summary>
90+
private LexicalDeclaration LexicalDeclaration()
91+
{
92+
var readOnly = CurrentIsKeyword("const");
93+
Expect("Keyword", readOnly ? "const" : "let");
94+
var declaration = new LexicalDeclaration(readOnly);
95+
96+
AddToDeclaration(declaration);
97+
98+
while (CurrentIs("Comma"))
99+
{
100+
Expect("Comma");
101+
AddToDeclaration(declaration);
102+
}
103+
104+
return declaration;
105+
}
106+
107+
/// <summary>
108+
/// Initialization -> Typed | Initializer
109+
/// Typed -> Type Initializer?
110+
/// Initializer -> '=' Expression
111+
/// </summary>
112+
private void AddToDeclaration(LexicalDeclaration declaration)
113+
{
114+
var ident = Expect("Ident");
115+
var identRef = new IdentifierReference(ident.Value) { Segment = ident.Segment };
116+
var assignment = new AssignmentExpression(
117+
new MemberExpression(identRef),
118+
new ImplicitLiteral(TypeIdentValue.Undefined))
119+
{ Segment = ident.Segment };
120+
121+
if (CurrentIs("Assign"))
122+
{
123+
var assignSegment = Expect("Assign").Segment;
124+
var expression = Expression();
125+
assignment = new AssignmentExpression(
126+
new MemberExpression(identRef), expression) { Segment = assignSegment };
127+
}
128+
else if (CurrentIs("Colon"))
129+
{
130+
Expect("Colon");
131+
var type = TypeValue();
132+
if (CurrentIs("Assign"))
133+
{
134+
var assignSegment = Expect("Assign").Segment;
135+
var expression = Expression();
136+
assignment = new AssignmentExpression(
137+
new MemberExpression(identRef),
138+
expression, type) { Segment = assignSegment };
139+
}
140+
else
141+
{
142+
var expression = new ImplicitLiteral(type);
143+
assignment = new AssignmentExpression(
144+
lhs: new MemberExpression(identRef),
145+
expression,
146+
type);
147+
}
148+
}
149+
150+
declaration.AddAssignment(assignment);
151+
}
152+
153+
/// <summary>
154+
/// TypeDeclaration -> 'type' "Ident" = TypeValue
155+
/// </summary>
156+
private TypeDeclaration TypeDeclaration()
157+
{
158+
var typeWord = Expect("Keyword", "type");
159+
var ident = Expect("Ident");
160+
Expect("Assign");
161+
var type = TypeValue();
162+
163+
var typeId = new IdentifierReference(name: ident.Value)
164+
{ Segment = ident.Segment };
165+
166+
return new TypeDeclaration(typeId, type) { Segment = typeWord.Segment + ident.Segment };
167+
}
168+
169+
/// <summary>
170+
/// TypeValue -> TypeValueBase TypeValueSuffix*
171+
/// </summary>
172+
private TypeValue TypeValue()
173+
{
174+
if (CurrentIs("Ident"))
175+
{
176+
var ident = Expect("Ident");
177+
var identType = new TypeIdentValue(
178+
TypeId: new IdentifierReference(name: ident.Value)
179+
{ Segment = ident.Segment });
180+
181+
return WithSuffix(identType);
182+
}
183+
184+
if (CurrentIs("LeftCurl"))
185+
{
186+
Expect("LeftCurl");
187+
var propertyTypes = new List<PropertyTypeValue>();
188+
while (CurrentIs("Ident"))
189+
{
190+
var ident = Expect("Ident");
191+
Expect("Colon");
192+
var propType = TypeValue();
193+
propertyTypes.Add(
194+
new PropertyTypeValue(
195+
ident.Value,
196+
propType));
197+
Expect("SemiColon");
198+
}
199+
200+
Expect("RightCurl");
201+
202+
return WithSuffix(new ObjectTypeValue(propertyTypes));
203+
}
204+
205+
return null!;
206+
}
207+
208+
/// <summary>
209+
/// TypeValueSuffix -> '['']' | '?'
210+
/// </summary>
211+
private TypeValue WithSuffix(TypeValue baseType)
212+
{
213+
var type = baseType;
214+
while (CurrentIs("LeftBracket") || CurrentIs("QuestionMark"))
215+
{
216+
if (CurrentIs("LeftBracket"))
217+
{
218+
Expect("LeftBracket");
219+
Expect("RightBracket");
220+
type = new ArrayTypeValue(type);
221+
}
222+
else if (CurrentIs("QuestionMark"))
223+
{
224+
Expect("QuestionMark");
225+
type = new NullableTypeValue(type);
226+
}
227+
}
228+
229+
return type;
230+
}
231+
}

0 commit comments

Comments
 (0)