| 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 /** | 5 /** |
| 6 * An event generating parser of Dart programs. This parser expects | 6 * An event generating parser of Dart programs. This parser expects |
| 7 * all tokens in a linked list. | 7 * all tokens in a linked list. |
| 8 */ | 8 */ |
| 9 class Parser<L extends Listener> { | 9 class PartialParser<L extends Listener> { |
| 10 final L listener; | 10 final L listener; |
| 11 | 11 |
| 12 Parser(L this.listener); | 12 // TODO(ahe): Clean up the following fields. |
| 13 Function beginTypeArguments; |
| 14 Function parseTypeFunction; |
| 15 Function endTypeArguments; |
| 16 Function handleNoTypeArguments; |
| 17 |
| 18 // TODO(ahe): Clean up the following fields. |
| 19 Function beginTypeVariables; |
| 20 Function parseTypeVariableFunction; |
| 21 Function endTypeVariables; |
| 22 Function handleNoTypeVariables; |
| 23 |
| 24 PartialParser(L this.listener) { |
| 25 beginTypeArguments = listener.beginTypeArguments; |
| 26 parseTypeFunction = parseType; |
| 27 endTypeArguments = listener.endTypeArguments; |
| 28 handleNoTypeArguments = listener.handleNoTypeArguments; |
| 29 |
| 30 beginTypeVariables = listener.beginTypeVariables; |
| 31 parseTypeVariableFunction = parseTypeVariable; |
| 32 endTypeVariables = listener.endTypeVariables; |
| 33 handleNoTypeVariables = listener.handleNoTypeVariables; |
| 34 |
| 35 if (parseTypeFunction === null) { |
| 36 // TODO(ahe): Work around bug in Frog optimizer. |
| 37 listener.beginTypeArguments(null); |
| 38 listener.endTypeArguments(0, null, null); |
| 39 listener.handleNoTypeArguments(null); |
| 40 listener.beginTypeVariables(null); |
| 41 parseTypeVariable(null); |
| 42 listener.endTypeVariables(0, null, null); |
| 43 listener.handleNoTypeVariables(null); |
| 44 } |
| 45 } |
| 13 | 46 |
| 14 // TODO(ahe): Rename this method. It is too subtle compared to token.next. | 47 // TODO(ahe): Rename this method. It is too subtle compared to token.next. |
| 15 Token next(Token token) => checkEof(token.next); | 48 Token next(Token token) => checkEof(token.next); |
| 16 | 49 |
| 17 Token checkEof(Token token) { | 50 Token checkEof(Token token) { |
| 18 if (token.kind === EOF_TOKEN) { | 51 if (token.kind === EOF_TOKEN) { |
| 19 listener.unexpectedEof(); | 52 listener.unexpectedEof(); |
| 20 throw 'Unexpected EOF'; | 53 throw 'Unexpected EOF'; |
| 21 } | 54 } |
| 22 return token; | 55 return token; |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 162 token = next(token); | 195 token = next(token); |
| 163 } while (token !== null); | 196 } while (token !== null); |
| 164 throw 'Internal error: unreachable code'; | 197 throw 'Internal error: unreachable code'; |
| 165 } | 198 } |
| 166 | 199 |
| 167 Token parseClass(Token token) { | 200 Token parseClass(Token token) { |
| 168 Token begin = token; | 201 Token begin = token; |
| 169 listener.beginClass(token); | 202 listener.beginClass(token); |
| 170 token = parseIdentifier(next(token)); | 203 token = parseIdentifier(next(token)); |
| 171 token = parseTypeVariablesOpt(token); | 204 token = parseTypeVariablesOpt(token); |
| 172 token = parseSuperclassClauseOpt(token); | 205 Token extendsKeyword; |
| 173 token = parseImplementsOpt(token); | 206 if (optional('extends', token)) { |
| 207 extendsKeyword = token; |
| 208 token = parseType(next(token)); |
| 209 } else { |
| 210 extendsKeyword = null; |
| 211 listener.handleNoType(token); |
| 212 } |
| 213 Token implementsKeyword; |
| 214 int interfacesCount = 0; |
| 215 if (optional('implements', token)) { |
| 216 do { |
| 217 token = parseType(next(token)); |
| 218 ++interfacesCount; |
| 219 } while (optional(',', token)); |
| 220 } |
| 174 token = parseNativeClassClauseOpt(token); | 221 token = parseNativeClassClauseOpt(token); |
| 175 token = parseClassBody(token); | 222 token = parseClassBody(token); |
| 176 listener.endClass(begin, token); | 223 listener.endClass(interfacesCount, begin, extendsKeyword, implementsKeyword, |
| 224 token); |
| 177 return token.next; | 225 return token.next; |
| 178 } | 226 } |
| 179 | 227 |
| 180 Token parseNativeClassClauseOpt(Token token) { | 228 Token parseNativeClassClauseOpt(Token token) { |
| 181 if (optional('native', token)) { | 229 if (optional('native', token)) { |
| 182 return parseString(next(token)); | 230 return parseString(next(token)); |
| 183 } | 231 } |
| 184 return token; | 232 return token; |
| 185 } | 233 } |
| 186 | 234 |
| 187 Token parseString(Token token) { | 235 Token parseString(Token token) { |
| 188 if (token.kind === STRING_TOKEN) { | 236 if (token.kind === STRING_TOKEN) { |
| 189 return next(token); | 237 return next(token); |
| 190 } else { | 238 } else { |
| 191 return listener.expected('string', token); | 239 return listener.expected('string', token); |
| 192 } | 240 } |
| 193 } | 241 } |
| 194 | 242 |
| 195 Token parseIdentifier(Token token) { | 243 Token parseIdentifier(Token token) { |
| 196 if (isIdentifier(token)) { | 244 if (isIdentifier(token)) { |
| 197 listener.handleIdentifier(token); | 245 listener.handleIdentifier(token); |
| 198 } else { | 246 } else { |
| 199 listener.expectedIdentifier(token); | 247 listener.expectedIdentifier(token); |
| 200 } | 248 } |
| 201 return next(token); | 249 return next(token); |
| 202 } | 250 } |
| 203 | 251 |
| 204 Token parseTypeVariablesOpt(Token token) { | |
| 205 if (!optional('<', token)) { | |
| 206 listener.handleNoTypeVariables(token); | |
| 207 return token; | |
| 208 } | |
| 209 return parseTypeVariables(token); | |
| 210 } | |
| 211 | |
| 212 Token parseTypeVariables(Token token) { | |
| 213 expect('<', token); | |
| 214 listener.beginTypeVariables(token); | |
| 215 do { | |
| 216 token = parseTypeVariable(next(token)); | |
| 217 } while (optional(',', token)); | |
| 218 listener.endTypeVariables(token); | |
| 219 return expect('>', token); | |
| 220 } | |
| 221 | |
| 222 Token expect(String string, Token token) { | 252 Token expect(String string, Token token) { |
| 223 if (string !== token.stringValue) { | 253 if (string !== token.stringValue) { |
| 224 return listener.expected(string, token); | 254 return listener.expected(string, token); |
| 225 } | 255 } |
| 226 return token.next; | 256 return token.next; |
| 227 } | 257 } |
| 228 | 258 |
| 229 Token parseTypeVariable(Token token) { | 259 Token parseTypeVariable(Token token) { |
| 230 listener.beginTypeVariable(token); | 260 listener.beginTypeVariable(token); |
| 231 token = parseIdentifier(token); | 261 token = parseIdentifier(token); |
| 232 token = parseSuperclassClauseOpt(token); | 262 if (optional('extends', token)) { |
| 263 token = parseType(next(token)); |
| 264 } else { |
| 265 listener.handleNoType(token); |
| 266 } |
| 233 listener.endTypeVariable(token); | 267 listener.endTypeVariable(token); |
| 234 return token; | 268 return token; |
| 235 } | 269 } |
| 236 | 270 |
| 237 bool optional(String value, Token token) => value === token.stringValue; | 271 bool optional(String value, Token token) => value === token.stringValue; |
| 238 | 272 |
| 239 Token parseSuperclassClauseOpt(Token token) { | |
| 240 if (optional('extends', token)) { | |
| 241 return parseType(next(token)); | |
| 242 } | |
| 243 return token; | |
| 244 } | |
| 245 | |
| 246 Token parseType(Token token) { | 273 Token parseType(Token token) { |
| 247 // TODO(ahe): Rename this method to parseTypeOrVar? | 274 // TODO(ahe): Rename this method to parseTypeOrVar? |
| 248 if (isIdentifier(token)) { | 275 if (isIdentifier(token)) { |
| 249 token = parseIdentifier(token); | 276 token = parseIdentifier(token); |
| 250 while (optional('.', token)) { | 277 while (optional('.', token)) { |
| 251 // TODO(ahe): Validate that there are at most two identifiers. | 278 // TODO(ahe): Validate that there are at most two identifiers. |
| 252 token = parseIdentifier(next(token)); | 279 token = parseIdentifier(next(token)); |
| 253 } | 280 } |
| 254 } else if (optional('var', token)) { | 281 } else if (optional('var', token)) { |
| 255 listener.handleVarKeyword(token); | 282 listener.handleVarKeyword(token); |
| 256 listener.endType(token); | 283 listener.endType(token); |
| 257 return next(token); | 284 return next(token); |
| 258 } else { | 285 } else { |
| 259 token = listener.expectedType(token); | 286 token = listener.expectedType(token); |
| 260 } | 287 } |
| 261 token = parseTypeArgumentsOpt(token); | 288 token = parseTypeArgumentsOpt(token); |
| 262 listener.endType(token); | 289 listener.endType(token); |
| 263 return token; | 290 return token; |
| 264 } | 291 } |
| 265 | 292 |
| 266 Token parseTypeArgumentsOpt(Token token) { | 293 Token parseTypeArgumentsOpt(Token token) { |
| 294 return parseStuff(token, beginTypeArguments, parseTypeFunction, |
| 295 endTypeArguments, handleNoTypeArguments); |
| 296 } |
| 297 |
| 298 Token parseTypeVariablesOpt(Token token) { |
| 299 return parseStuff(token, beginTypeVariables, parseTypeVariableFunction, |
| 300 endTypeVariables, handleNoTypeVariables); |
| 301 } |
| 302 |
| 303 // TODO(ahe): Clean this up. |
| 304 Token parseStuff(Token token, Function beginStuff, Function stuffParser, |
| 305 Function endStuff, Function handleNoStuff) { |
| 267 if (optional('<', token)) { | 306 if (optional('<', token)) { |
| 268 listener.beginTypeArguments(next(token)); | 307 Token begin = token; |
| 308 beginStuff(begin); |
| 309 int count = 0; |
| 269 do { | 310 do { |
| 270 token = parseType(next(token)); | 311 token = stuffParser(next(token)); |
| 312 ++count; |
| 271 } while (optional(',', token)); | 313 } while (optional(',', token)); |
| 314 endStuff(count, begin, token); |
| 272 return expect('>', token); | 315 return expect('>', token); |
| 273 } | 316 } |
| 317 handleNoStuff(token); |
| 274 return token; | 318 return token; |
| 275 } | 319 } |
| 276 | 320 |
| 277 Token parseImplementsOpt(Token token) { | |
| 278 if (optional('implements', token)) { | |
| 279 do { | |
| 280 token = parseType(next(token)); | |
| 281 } while (optional(',', token)); | |
| 282 } | |
| 283 return token; | |
| 284 } | |
| 285 | |
| 286 Token parseClassBody(Token token) => skipBlock(token); | 321 Token parseClassBody(Token token) => skipBlock(token); |
| 287 | 322 |
| 288 Token parseTopLevelMember(Token token) { | 323 Token parseTopLevelMember(Token token) { |
| 289 Token start = token; | 324 Token start = token; |
| 290 listener.beginTopLevelMember(token); | 325 listener.beginTopLevelMember(token); |
| 291 Token previous = token; | 326 Token previous = token; |
| 292 LOOP: while (token !== null) { | 327 LOOP: while (token !== null) { |
| 293 final kind = token.kind; | 328 final kind = token.kind; |
| 294 switch (true) { | 329 switch (true) { |
| 295 case kind === LBRACE_TOKEN: | 330 case kind === LBRACE_TOKEN: |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 341 while (token !== null && | 376 while (token !== null && |
| 342 token.kind !== LPAREN_TOKEN && | 377 token.kind !== LPAREN_TOKEN && |
| 343 token.kind !== RPAREN_TOKEN) { | 378 token.kind !== RPAREN_TOKEN) { |
| 344 token = next(token); | 379 token = next(token); |
| 345 } | 380 } |
| 346 token = expect(')', token); | 381 token = expect(')', token); |
| 347 return expect(';', token); | 382 return expect(';', token); |
| 348 } | 383 } |
| 349 } | 384 } |
| 350 | 385 |
| 351 class BodyParser extends Parser/* <BodyListener> Frog bug #320 */ { | 386 class Parser extends PartialParser/* <NodeListener> Frog bug #320 */ { |
| 352 BodyParser(BodyListener listener) : super(listener); | 387 Parser(NodeListener listener) : super(listener); |
| 353 | 388 |
| 354 Token parseFunction(Token token) { | 389 Token parseFunction(Token token) { |
| 355 listener.beginFunction(token); | 390 listener.beginFunction(token); |
| 356 token = parseReturnTypeOpt(token); | 391 token = parseReturnTypeOpt(token); |
| 357 listener.beginFunctionName(token); | 392 listener.beginFunctionName(token); |
| 358 token = parseIdentifier(token); | 393 token = parseIdentifier(token); |
| 359 listener.endFunctionName(token); | 394 listener.endFunctionName(token); |
| 360 token = parseFormalParameters(token); | 395 token = parseFormalParameters(token); |
| 361 return parseFunctionBody(token); | 396 return parseFunctionBody(token); |
| 362 } | 397 } |
| (...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 710 if (optional(';', token)) { | 745 if (optional(';', token)) { |
| 711 listener.endRethrowStatement(throwToken, token); | 746 listener.endRethrowStatement(throwToken, token); |
| 712 return token.next; | 747 return token.next; |
| 713 } else { | 748 } else { |
| 714 token = parseExpression(token); | 749 token = parseExpression(token); |
| 715 listener.endThrowStatement(throwToken, token); | 750 listener.endThrowStatement(throwToken, token); |
| 716 return expectSemicolon(token); | 751 return expectSemicolon(token); |
| 717 } | 752 } |
| 718 } | 753 } |
| 719 } | 754 } |
| OLD | NEW |