OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library dart2js.parser.partial; | 5 library parser.top_level_parser; |
6 | 6 |
7 import '../common.dart'; | 7 import 'package:scanner/src/token.dart' show |
8 import '../options.dart' show ParserOptions; | 8 BeginGroupToken, |
9 import '../tokens/token.dart' show BeginGroupToken, ErrorToken, Token; | 9 Token; |
10 import '../tokens/token_constants.dart' as Tokens show EOF_TOKEN; | |
11 import '../util/characters.dart' as Characters show $CLOSE_CURLY_BRACKET; | |
12 import 'listener.dart' show Listener; | |
13 import 'parser.dart' show Parser; | |
14 | 10 |
15 class PartialParser extends Parser { | 11 import 'package:scanner/src/characters.dart' show |
16 PartialParser(Listener listener, ParserOptions options) | 12 $CLOSE_CURLY_BRACKET; |
17 : super(listener, options); | |
18 | 13 |
19 Token parseClassBody(Token token) => skipClassBody(token); | 14 import 'listener.dart' show |
| 15 Listener; |
20 | 16 |
21 Token fullParseClassBody(Token token) => super.parseClassBody(token); | 17 import 'class_member_parser.dart' show |
| 18 ClassMemberParser; |
22 | 19 |
23 Token parseExpression(Token token) => skipExpression(token); | 20 import 'parser.dart' show |
| 21 optional; |
24 | 22 |
25 Token parseArgumentsOpt(Token token) { | 23 /// Parser which only parses top-level elements, but ignores their bodies. |
26 // This method is overridden for two reasons: | 24 /// Use [Parser] to parse everything. |
27 // 1. Avoid generating events for arguments. | 25 class TopLevelParser extends ClassMemberParser { |
28 // 2. Avoid calling skip expression for each argument (which doesn't work). | 26 TopLevelParser(Listener listener, |
29 listener.handleNoArguments(token); | 27 {bool asyncAwaitKeywordsEnabled: false, |
30 if (optional('(', token)) { | 28 bool enableGenericMethodSyntax: false}) |
31 BeginGroupToken begin = token; | 29 : super(listener, asyncAwaitKeywordsEnabled: asyncAwaitKeywordsEnabled, |
32 return begin.endGroup.next; | 30 enableGenericMethodSyntax: enableGenericMethodSyntax); |
33 } else { | |
34 return token; | |
35 } | |
36 } | |
37 | 31 |
38 Token skipExpression(Token token) { | 32 Token parseClassBody(Token token) { |
39 while (true) { | |
40 final kind = token.kind; | |
41 final value = token.stringValue; | |
42 if ((identical(kind, Tokens.EOF_TOKEN)) || | |
43 (identical(value, ';')) || | |
44 (identical(value, ',')) || | |
45 (identical(value, '}')) || | |
46 (identical(value, ')')) || | |
47 (identical(value, ']'))) { | |
48 break; | |
49 } | |
50 if (identical(value, '=') || | |
51 identical(value, '?') || | |
52 identical(value, ':') || | |
53 identical(value, '??')) { | |
54 var nextValue = token.next.stringValue; | |
55 if (identical(nextValue, 'const')) { | |
56 token = token.next; | |
57 nextValue = token.next.stringValue; | |
58 } | |
59 if (identical(nextValue, '{')) { | |
60 // Handle cases like this: | |
61 // class Foo { | |
62 // var map; | |
63 // Foo() : map = {}; | |
64 // Foo.x() : map = true ? {} : {}; | |
65 // } | |
66 BeginGroupToken begin = token.next; | |
67 token = (begin.endGroup != null) ? begin.endGroup : token; | |
68 token = token.next; | |
69 continue; | |
70 } | |
71 if (identical(nextValue, '<')) { | |
72 // Handle cases like this: | |
73 // class Foo { | |
74 // var map; | |
75 // Foo() : map = <String, Foo>{}; | |
76 // Foo.x() : map = true ? <String, Foo>{} : <String, Foo>{}; | |
77 // } | |
78 BeginGroupToken begin = token.next; | |
79 token = (begin.endGroup != null) ? begin.endGroup : token; | |
80 token = token.next; | |
81 if (identical(token.stringValue, '{')) { | |
82 begin = token; | |
83 token = (begin.endGroup != null) ? begin.endGroup : token; | |
84 token = token.next; | |
85 } | |
86 continue; | |
87 } | |
88 } | |
89 if (!mayParseFunctionExpressions && identical(value, '{')) { | |
90 break; | |
91 } | |
92 if (token is BeginGroupToken) { | |
93 BeginGroupToken begin = token; | |
94 token = (begin.endGroup != null) ? begin.endGroup : token; | |
95 } else if (token is ErrorToken) { | |
96 listener.reportErrorToken(token); | |
97 } | |
98 token = token.next; | |
99 } | |
100 return token; | |
101 } | |
102 | |
103 Token skipClassBody(Token token) { | |
104 if (!optional('{', token)) { | 33 if (!optional('{', token)) { |
105 return listener.expectedClassBodyToSkip(token); | 34 return listener.expectedClassBodyToSkip(token); |
106 } | 35 } |
107 BeginGroupToken beginGroupToken = token; | 36 BeginGroupToken beginGroupToken = token; |
108 Token endGroup = beginGroupToken.endGroup; | 37 Token endGroup = beginGroupToken.endGroup; |
109 if (endGroup == null) { | 38 if (endGroup == null) { |
110 return listener.unmatched(beginGroupToken); | 39 return listener.unmatched(beginGroupToken); |
111 } else if (!identical(endGroup.kind, Characters.$CLOSE_CURLY_BRACKET)) { | 40 } else if (!identical(endGroup.kind, $CLOSE_CURLY_BRACKET)) { |
112 return listener.unmatched(beginGroupToken); | 41 return listener.unmatched(beginGroupToken); |
113 } | 42 } |
114 return endGroup; | 43 return endGroup; |
115 } | 44 } |
116 | |
117 Token skipAsyncModifier(Token token) { | |
118 String value = token.stringValue; | |
119 if (identical(value, 'async')) { | |
120 token = token.next; | |
121 value = token.stringValue; | |
122 | |
123 if (identical(value, '*')) { | |
124 token = token.next; | |
125 } | |
126 } else if (identical(value, 'sync')) { | |
127 token = token.next; | |
128 value = token.stringValue; | |
129 | |
130 if (identical(value, '*')) { | |
131 token = token.next; | |
132 } | |
133 } | |
134 return token; | |
135 } | |
136 | |
137 Token parseFunctionBody(Token token, bool isExpression, bool allowAbstract) { | |
138 assert(!isExpression); | |
139 token = skipAsyncModifier(token); | |
140 String value = token.stringValue; | |
141 if (identical(value, ';')) { | |
142 if (!allowAbstract) { | |
143 listener.reportError(token, MessageKind.BODY_EXPECTED); | |
144 } | |
145 listener.handleNoFunctionBody(token); | |
146 } else { | |
147 if (identical(value, '=>')) { | |
148 token = parseExpression(token.next); | |
149 expectSemicolon(token); | |
150 } else if (value == '=') { | |
151 token = parseRedirectingFactoryBody(token); | |
152 expectSemicolon(token); | |
153 } else { | |
154 token = skipBlock(token); | |
155 } | |
156 listener.skippedFunctionBody(token); | |
157 } | |
158 return token; | |
159 } | |
160 | |
161 Token parseFormalParameters(Token token) => skipFormals(token); | |
162 | |
163 Token skipFormals(Token token) { | |
164 listener.beginOptionalFormalParameters(token); | |
165 if (!optional('(', token)) { | |
166 if (optional(';', token)) { | |
167 listener.recoverableError(token, "expected '('"); | |
168 return token; | |
169 } | |
170 return listener.unexpected(token); | |
171 } | |
172 BeginGroupToken beginGroupToken = token; | |
173 Token endToken = beginGroupToken.endGroup; | |
174 listener.endFormalParameters(0, token, endToken); | |
175 return endToken.next; | |
176 } | |
177 } | 45 } |
OLD | NEW |