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