Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(30)

Side by Side Diff: pkg/compiler/lib/src/scanner/class_element_parser.dart

Issue 1313073007: Move parser and token related libraries into their own subfolder. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Fix unittests and try Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 library dart2js.parser.classes;
6
7 import '../compiler.dart' show
8 Compiler;
9 import '../diagnostics/diagnostic_listener.dart' show
10 DiagnosticListener;
11 import '../diagnostics/messages.dart' show
12 MessageKind;
13 import '../diagnostics/invariant.dart' show
14 invariant;
15 import '../elements/elements.dart' show
16 CompilationUnitElement,
17 Element,
18 ElementKind,
19 Elements,
20 MetadataAnnotation,
21 STATE_NOT_STARTED,
22 STATE_DONE;
23 import '../elements/modelx.dart' show
24 ClassElementX,
25 ElementX,
26 FieldElementX,
27 VariableList;
28 import '../elements/visitor.dart' show
29 ElementVisitor;
30 import '../tree/tree.dart';
31 import '../util/util.dart' show
32 Link;
33
34 import 'listener.dart' show
35 Listener,
36 NodeListener,
37 ParserError,
38 PartialConstructorElement,
39 PartialElement,
40 PartialFunctionElement,
41 PartialMetadataAnnotation;
42 import 'parser.dart' show
43 Parser;
44 import 'partial_parser.dart' show
45 PartialParser;
46 import 'token.dart' show
47 Token;
48
49 class ClassElementParser extends PartialParser {
50 ClassElementParser(Listener listener) : super(listener);
51
52 Token parseClassBody(Token token) => fullParseClassBody(token);
53 }
54
55 class PartialClassElement extends ClassElementX with PartialElement {
56 ClassNode cachedNode;
57
58 PartialClassElement(String name,
59 Token beginToken,
60 Token endToken,
61 Element enclosing,
62 int id)
63 : super(name, enclosing, id, STATE_NOT_STARTED) {
64 this.beginToken = beginToken;
65 this.endToken = endToken;
66 }
67
68 void set supertypeLoadState(int state) {
69 assert(state == STATE_NOT_STARTED || state == supertypeLoadState + 1);
70 assert(state <= STATE_DONE);
71 super.supertypeLoadState = state;
72 }
73
74 void set resolutionState(int state) {
75 assert(state == STATE_NOT_STARTED || state == resolutionState + 1);
76 assert(state <= STATE_DONE);
77 super.resolutionState = state;
78 }
79
80 bool get hasNode => cachedNode != null;
81
82 ClassNode get node {
83 assert(invariant(this, cachedNode != null,
84 message: "Node has not been computed for $this."));
85 return cachedNode;
86 }
87
88 ClassNode parseNode(Compiler compiler) {
89 if (cachedNode != null) return cachedNode;
90 compiler.withCurrentElement(this, () {
91 compiler.parser.measure(() {
92 MemberListener listener = new MemberListener(compiler, this);
93 Parser parser = new ClassElementParser(listener);
94 try {
95 Token token = parser.parseTopLevelDeclaration(beginToken);
96 assert(identical(token, endToken.next));
97 cachedNode = listener.popNode();
98 assert(
99 invariant(
100 beginToken, listener.nodes.isEmpty,
101 message: "Non-empty listener stack: ${listener.nodes}"));
102 } on ParserError {
103 // TODO(ahe): Often, a ParserError is thrown while parsing the class
104 // body. This means that the stack actually contains most of the
105 // information synthesized below. Consider rewriting the parser so
106 // endClassDeclaration is called before parsing the class body.
107 Identifier name = new Identifier(findMyName(beginToken));
108 NodeList typeParameters = null;
109 Node supertype = null;
110 NodeList interfaces = listener.makeNodeList(0, null, null, ",");
111 Token extendsKeyword = null;
112 NodeList body = listener.makeNodeList(0, beginToken, endToken, null);
113 cachedNode = new ClassNode(
114 Modifiers.EMPTY, name, typeParameters, supertype, interfaces,
115 beginToken, extendsKeyword, body, endToken);
116 hasParseError = true;
117 }
118 });
119 compiler.patchParser.measure(() {
120 if (isPatched) {
121 // TODO(lrn): Perhaps extract functionality so it doesn't
122 // need compiler.
123 compiler.patchParser.parsePatchClassNode(patch);
124 }
125 });
126 });
127 return cachedNode;
128 }
129
130 Token get position => beginToken;
131
132 // TODO(johnniwinther): Ensure that modifiers are always available.
133 Modifiers get modifiers =>
134 cachedNode != null ? cachedNode.modifiers : Modifiers.EMPTY;
135
136 accept(ElementVisitor visitor, arg) {
137 return visitor.visitClassElement(this, arg);
138 }
139
140 PartialClassElement copyWithEnclosing(CompilationUnitElement enclosing) {
141 return new PartialClassElement(name, beginToken, endToken, enclosing, id);
142 }
143 }
144
145 class MemberListener extends NodeListener {
146 final ClassElementX enclosingClass;
147
148 MemberListener(DiagnosticListener listener,
149 ClassElementX enclosingElement)
150 : this.enclosingClass = enclosingElement,
151 super(listener, enclosingElement.compilationUnit);
152
153 bool isConstructorName(Node nameNode) {
154 if (enclosingClass == null ||
155 enclosingClass.kind != ElementKind.CLASS) {
156 return false;
157 }
158 String name;
159 if (nameNode.asIdentifier() != null) {
160 name = nameNode.asIdentifier().source;
161 } else {
162 Send send = nameNode.asSend();
163 name = send.receiver.asIdentifier().source;
164 }
165 return enclosingClass.name == name;
166 }
167
168 // TODO(johnniwinther): Remove this method.
169 String getMethodNameHack(Node methodName) {
170 Send send = methodName.asSend();
171 if (send == null) {
172 if (isConstructorName(methodName)) return '';
173 return methodName.asIdentifier().source;
174 }
175 Identifier receiver = send.receiver.asIdentifier();
176 Identifier selector = send.selector.asIdentifier();
177 Operator operator = selector.asOperator();
178 if (operator != null) {
179 assert(identical(receiver.source, 'operator'));
180 // TODO(ahe): It is a hack to compare to ')', but it beats
181 // parsing the node.
182 bool isUnary = identical(operator.token.next.next.stringValue, ')');
183 return Elements.constructOperatorName(operator.source, isUnary);
184 } else {
185 if (receiver == null || receiver.source != enclosingClass.name) {
186 listener.reportError(send.receiver,
187 MessageKind.INVALID_CONSTRUCTOR_NAME,
188 {'name': enclosingClass.name});
189 }
190 return selector.source;
191 }
192 }
193
194 void endMethod(Token getOrSet, Token beginToken, Token endToken) {
195 super.endMethod(getOrSet, beginToken, endToken);
196 FunctionExpression method = popNode();
197 pushNode(null);
198 bool isConstructor = isConstructorName(method.name);
199 String name = getMethodNameHack(method.name);
200 Element memberElement;
201 if (isConstructor) {
202 if (getOrSet != null) {
203 recoverableError(getOrSet, 'illegal modifier');
204 }
205 memberElement = new PartialConstructorElement(
206 name, beginToken, endToken,
207 ElementKind.GENERATIVE_CONSTRUCTOR,
208 method.modifiers,
209 enclosingClass);
210 } else {
211 memberElement = new PartialFunctionElement(
212 name, beginToken, getOrSet, endToken,
213 method.modifiers, enclosingClass, hasBody: method.hasBody());
214 }
215 addMember(memberElement);
216 }
217
218 void endFactoryMethod(Token beginToken, Token endToken) {
219 super.endFactoryMethod(beginToken, endToken);
220 FunctionExpression method = popNode();
221 pushNode(null);
222 String name = getMethodNameHack(method.name);
223 Identifier singleIdentifierName = method.name.asIdentifier();
224 if (singleIdentifierName != null && singleIdentifierName.source == name) {
225 if (name != enclosingClass.name) {
226 listener.reportError(singleIdentifierName,
227 MessageKind.INVALID_UNNAMED_CONSTRUCTOR_NAME,
228 {'name': enclosingClass.name});
229 }
230 }
231 Element memberElement = new PartialConstructorElement(
232 name, beginToken, endToken,
233 ElementKind.FUNCTION,
234 method.modifiers,
235 enclosingClass);
236 addMember(memberElement);
237 }
238
239 void endFields(int count, Token beginToken, Token endToken) {
240 bool hasParseError = memberErrors.head;
241 super.endFields(count, beginToken, endToken);
242 VariableDefinitions variableDefinitions = popNode();
243 Modifiers modifiers = variableDefinitions.modifiers;
244 pushNode(null);
245 void buildFieldElement(Identifier name, VariableList fields) {
246 Element element =
247 new FieldElementX(name, enclosingClass, fields);
248 addMember(element);
249 }
250 buildFieldElements(modifiers, variableDefinitions.definitions,
251 enclosingClass,
252 buildFieldElement, beginToken, endToken,
253 hasParseError);
254 }
255
256 void endInitializer(Token assignmentOperator) {
257 pushNode(null); // Super expects an expression, but
258 // ClassElementParser just skips expressions.
259 super.endInitializer(assignmentOperator);
260 }
261
262 void endInitializers(int count, Token beginToken, Token endToken) {
263 pushNode(null);
264 }
265
266 void addMetadata(ElementX memberElement) {
267 for (Link link = metadata; !link.isEmpty; link = link.tail) {
268 memberElement.addMetadata(link.head);
269 }
270 metadata = const Link<MetadataAnnotation>();
271 }
272
273 void addMember(ElementX memberElement) {
274 addMetadata(memberElement);
275 enclosingClass.addMember(memberElement, listener);
276 }
277
278 void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) {
279 popNode(); // Discard arguments.
280 if (periodBeforeName != null) {
281 popNode(); // Discard name.
282 }
283 popNode(); // Discard node (Send or Identifier).
284 pushMetadata(new PartialMetadataAnnotation(beginToken, endToken));
285 }
286 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/scanner/array_based_scanner.dart ('k') | pkg/compiler/lib/src/scanner/diet_parser_task.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698