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

Side by Side Diff: pkg/compiler/lib/src/parser/parser.dart

Issue 1878253002: Adds support for remaining generic method syntax constructs. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Added comment at a tricky point Created 4 years, 8 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
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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; 5 library dart2js.parser;
6 6
7 import '../options.dart' show ParserOptions; 7 import '../options.dart' show ParserOptions;
8 import '../common.dart'; 8 import '../common.dart';
9 import '../tokens/keyword.dart' show Keyword; 9 import '../tokens/keyword.dart' show Keyword;
10 import '../tokens/precedence.dart' show PrecedenceInfo; 10 import '../tokens/precedence.dart' show PrecedenceInfo;
(...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after
456 token = parseReturnTypeOpt(token); 456 token = parseReturnTypeOpt(token);
457 Token thisKeyword = null; 457 Token thisKeyword = null;
458 if (optional('this', token)) { 458 if (optional('this', token)) {
459 thisKeyword = token; 459 thisKeyword = token;
460 // TODO(ahe): Validate field initializers are only used in 460 // TODO(ahe): Validate field initializers are only used in
461 // constructors, and not for function-typed arguments. 461 // constructors, and not for function-typed arguments.
462 token = expect('.', token.next); 462 token = expect('.', token.next);
463 } 463 }
464 token = parseIdentifier(token); 464 token = parseIdentifier(token);
465 if (optional('(', token)) { 465 if (optional('(', token)) {
466 listener.handleNoTypeVariables(token);
467 token = parseFormalParameters(token);
468 listener.handleFunctionTypedFormalParameter(token);
469 } else if (enableGenericMethodSyntax && optional('<', token)) {
470 token = parseTypeVariablesOpt(token);
466 token = parseFormalParameters(token); 471 token = parseFormalParameters(token);
467 listener.handleFunctionTypedFormalParameter(token); 472 listener.handleFunctionTypedFormalParameter(token);
468 } 473 }
469 String value = token.stringValue; 474 String value = token.stringValue;
470 if ((identical('=', value)) || (identical(':', value))) { 475 if ((identical('=', value)) || (identical(':', value))) {
471 // TODO(ahe): Validate that these are only used for optional parameters. 476 // TODO(ahe): Validate that these are only used for optional parameters.
472 Token equal = token; 477 Token equal = token;
473 token = parseExpression(token.next); 478 token = parseExpression(token.next);
474 listener.handleValuedFormalParameter(equal, token); 479 listener.handleValuedFormalParameter(equal, token);
475 if (type.isRequired) { 480 if (type.isRequired) {
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after
760 Token expect(String string, Token token) { 765 Token expect(String string, Token token) {
761 if (!identical(string, token.stringValue)) { 766 if (!identical(string, token.stringValue)) {
762 return listener.expected(string, token); 767 return listener.expected(string, token);
763 } 768 }
764 return token.next; 769 return token.next;
765 } 770 }
766 771
767 Token parseTypeVariable(Token token) { 772 Token parseTypeVariable(Token token) {
768 listener.beginTypeVariable(token); 773 listener.beginTypeVariable(token);
769 token = parseIdentifier(token); 774 token = parseIdentifier(token);
770 if (optional('extends', token)) { 775 if (optional('extends', token) ||
776 (enableGenericMethodSyntax && optional('super', token))) {
777 listener.handleExtendsOrSuper(token);
771 token = parseType(token.next); 778 token = parseType(token.next);
772 } else { 779 } else {
780 listener.handleNoExtendsNorSuper(token);
773 listener.handleNoType(token); 781 listener.handleNoType(token);
774 } 782 }
775 listener.endTypeVariable(token); 783 listener.endTypeVariable(token);
Johnni Winther 2016/04/13 11:50:19 Remove 'handleExtendsOrSuper' and 'handleNoExtends
eernst 2016/04/13 17:08:26 Done.
776 return token; 784 return token;
777 } 785 }
778 786
779 /** 787 /**
780 * Returns true if the stringValue of the [token] is [value]. 788 * Returns true if the stringValue of the [token] is [value].
781 */ 789 */
782 bool optional(String value, Token token) { 790 bool optional(String value, Token token) {
783 return identical(value, token.stringValue); 791 return identical(value, token.stringValue);
784 } 792 }
785 793
(...skipping 1051 matching lines...) Expand 10 before | Expand all | Expand 10 after
1837 Token afterId = identifier.next; 1845 Token afterId = identifier.next;
1838 int afterIdKind = afterId.kind; 1846 int afterIdKind = afterId.kind;
1839 if (identical(afterIdKind, EQ_TOKEN) || 1847 if (identical(afterIdKind, EQ_TOKEN) ||
1840 identical(afterIdKind, SEMICOLON_TOKEN) || 1848 identical(afterIdKind, SEMICOLON_TOKEN) ||
1841 identical(afterIdKind, COMMA_TOKEN)) { 1849 identical(afterIdKind, COMMA_TOKEN)) {
1842 // We are looking at "type identifier" followed by '=', ';', ','. 1850 // We are looking at "type identifier" followed by '=', ';', ','.
1843 return parseVariablesDeclaration(token); 1851 return parseVariablesDeclaration(token);
1844 } else if (identical(afterIdKind, OPEN_PAREN_TOKEN)) { 1852 } else if (identical(afterIdKind, OPEN_PAREN_TOKEN)) {
1845 // We are looking at "type identifier '('". 1853 // We are looking at "type identifier '('".
1846 BeginGroupToken beginParen = afterId; 1854 BeginGroupToken beginParen = afterId;
1847 Token endParen = beginParen.endGroup; 1855 Token endParen = beginParen.endGroup;
karlklose 2016/04/13 12:26:55 Consider creating an issue for this and change the
eernst 2016/04/13 17:08:26 Done.
1856 // TODO(eernst): Check this, looks like an NPE with unbalanced parens.
Johnni Winther 2016/04/13 11:50:19 Do you have examples that trigger this (and others
eernst 2016/04/13 17:08:26 No, I hoped to get a quick confirmation like "That
1848 Token afterParens = endParen.next; 1857 Token afterParens = endParen.next;
1849 if (optional('{', afterParens) || 1858 if (optional('{', afterParens) ||
1850 optional('=>', afterParens) || 1859 optional('=>', afterParens) ||
1851 optional('async', afterParens) || 1860 optional('async', afterParens) ||
1852 optional('sync', afterParens)) { 1861 optional('sync', afterParens)) {
1853 // We are looking at "type identifier '(' ... ')'" followed 1862 // We are looking at "type identifier '(' ... ')'" followed
1854 // by '=>' or '{'. 1863 // by '{', '=>', 'async', or 'sync'.
1855 return parseFunctionDeclaration(token); 1864 return parseFunctionDeclaration(token);
1856 } 1865 }
1866 } else if (enableGenericMethodSyntax &&
1867 identical(afterIdKind, LT_TOKEN)) {
1868 // We are looking at "type identifier '<'".
1869 BeginGroupToken beginAngle = afterId;
1870 Token endAngle = beginAngle.endGroup;
1871 if (endAngle != null &&
1872 identical(endAngle.next.kind, OPEN_PAREN_TOKEN)) {
1873 BeginGroupToken beginParen = endAngle.next;
1874 Token endParen = beginParen.endGroup;
1875 if (endParen != null) {
1876 Token afterParens = endParen.next;
1877 if (optional('{', afterParens) ||
1878 optional('=>', afterParens) ||
1879 optional('async', afterParens) ||
1880 optional('sync', afterParens)) {
1881 // We are looking at "type identifier '<' ... '>' '(' ... ')'"
1882 // followed by '{', '=>', 'async', or 'sync'.
1883 return parseFunctionDeclaration(token);
1884 }
1885 }
1886 }
1857 } 1887 }
1858 // Fall-through to expression statement. 1888 // Fall-through to expression statement.
1859 } else { 1889 } else {
1860 if (optional(':', token.next)) { 1890 if (optional(':', token.next)) {
1861 return parseLabeledStatement(token); 1891 return parseLabeledStatement(token);
1862 } else if (optional('(', token.next)) { 1892 } else if (optional('(', token.next)) {
1863 BeginGroupToken begin = token.next; 1893 BeginGroupToken begin = token.next;
1894 // TODO(eernst): Check this, looks like an NPE with unbalanced parens.
1864 String afterParens = begin.endGroup.next.stringValue; 1895 String afterParens = begin.endGroup.next.stringValue;
1865 if (identical(afterParens, '{') || 1896 if (identical(afterParens, '{') ||
1866 identical(afterParens, '=>') || 1897 identical(afterParens, '=>') ||
1867 identical(afterParens, 'async') || 1898 identical(afterParens, 'async') ||
1868 identical(afterParens, 'sync')) { 1899 identical(afterParens, 'sync')) {
1869 return parseFunctionDeclaration(token); 1900 return parseFunctionDeclaration(token);
1870 } 1901 }
1902 } else if (enableGenericMethodSyntax && optional('<', token.next)) {
1903 BeginGroupToken beginAngle = token.next;
1904 Token endAngle = beginAngle.endGroup;
1905 if (endAngle != null &&
1906 identical(endAngle.next.kind, OPEN_PAREN_TOKEN)) {
1907 BeginGroupToken beginParen = endAngle.next;
1908 Token endParen = beginParen.endGroup;
1909 if (endParen != null) {
1910 String afterParens = endParen.next.stringValue;
1911 if (identical(afterParens, '{') ||
1912 identical(afterParens, '=>') ||
1913 identical(afterParens, 'async') ||
1914 identical(afterParens, 'sync')) {
1915 return parseFunctionDeclaration(token);
1916 }
1917 }
1918 }
1919 // Fall through to expression statement.
1871 } 1920 }
1872 } 1921 }
1873 return parseExpressionStatement(token); 1922 return parseExpressionStatement(token);
1874 } 1923 }
1875 1924
1876 Token parseExpressionStatementOrConstDeclaration(Token token) { 1925 Token parseExpressionStatementOrConstDeclaration(Token token) {
1877 assert(identical(token.stringValue, 'const')); 1926 assert(identical(token.stringValue, 'const'));
1878 if (isModifier(token.next)) { 1927 if (isModifier(token.next)) {
1879 return parseVariablesDeclaration(token); 1928 return parseVariablesDeclaration(token);
1880 } 1929 }
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
2132 return parseSendOrFunctionLiteral(token); 2181 return parseSendOrFunctionLiteral(token);
2133 } else { 2182 } else {
2134 return listener.expectedExpression(token); 2183 return listener.expectedExpression(token);
2135 } 2184 }
2136 } else if (kind == OPEN_PAREN_TOKEN) { 2185 } else if (kind == OPEN_PAREN_TOKEN) {
2137 return parseParenthesizedExpressionOrFunctionLiteral(token); 2186 return parseParenthesizedExpressionOrFunctionLiteral(token);
2138 } else if ((kind == LT_TOKEN) || 2187 } else if ((kind == LT_TOKEN) ||
2139 (kind == OPEN_SQUARE_BRACKET_TOKEN) || 2188 (kind == OPEN_SQUARE_BRACKET_TOKEN) ||
2140 (kind == OPEN_CURLY_BRACKET_TOKEN) || 2189 (kind == OPEN_CURLY_BRACKET_TOKEN) ||
2141 token.stringValue == '[]') { 2190 token.stringValue == '[]') {
2142 return parseLiteralListOrMap(token); 2191 return parseLiteralListOrMapOrFunction(token);
2143 } else { 2192 } else {
2144 return listener.expectedExpression(token); 2193 return listener.expectedExpression(token);
2145 } 2194 }
2146 } 2195 }
2147 2196
2148 Token parseParenthesizedExpressionOrFunctionLiteral(Token token) { 2197 Token parseParenthesizedExpressionOrFunctionLiteral(Token token) {
2149 BeginGroupToken beginGroup = token; 2198 BeginGroupToken beginGroup = token;
2199 // TODO(eernst): Check this, looks like an NPE with unbalanced parens.
2150 Token nextToken = beginGroup.endGroup.next; 2200 Token nextToken = beginGroup.endGroup.next;
2151 int kind = nextToken.kind; 2201 int kind = nextToken.kind;
2152 if (mayParseFunctionExpressions && 2202 if (mayParseFunctionExpressions &&
2153 (identical(kind, FUNCTION_TOKEN) || 2203 (identical(kind, FUNCTION_TOKEN) ||
2154 identical(kind, OPEN_CURLY_BRACKET_TOKEN) || 2204 identical(kind, OPEN_CURLY_BRACKET_TOKEN) ||
2155 (identical(kind, KEYWORD_TOKEN) && 2205 (identical(kind, KEYWORD_TOKEN) &&
2156 (nextToken.value == 'async' || nextToken.value == 'sync')))) { 2206 (nextToken.value == 'async' || nextToken.value == 'sync')))) {
2207 listener.handleNoTypeVariables(token);
2157 return parseUnnamedFunction(token); 2208 return parseUnnamedFunction(token);
2158 } else { 2209 } else {
2159 bool old = mayParseFunctionExpressions; 2210 bool old = mayParseFunctionExpressions;
2160 mayParseFunctionExpressions = true; 2211 mayParseFunctionExpressions = true;
2161 token = parseParenthesizedExpression(token); 2212 token = parseParenthesizedExpression(token);
2162 mayParseFunctionExpressions = old; 2213 mayParseFunctionExpressions = old;
2163 return token; 2214 return token;
2164 } 2215 }
2165 } 2216 }
2166 2217
(...skipping 29 matching lines...) Expand all
2196 token = token.next; 2247 token = token.next;
2197 if (optional('(', token)) { 2248 if (optional('(', token)) {
2198 // Super constructor. 2249 // Super constructor.
2199 listener.handleNoTypeArguments(token); 2250 listener.handleNoTypeArguments(token);
2200 token = parseArguments(token); 2251 token = parseArguments(token);
2201 listener.endSend(token); 2252 listener.endSend(token);
2202 } 2253 }
2203 return token; 2254 return token;
2204 } 2255 }
2205 2256
2206 Token parseLiteralListOrMap(Token token) { 2257 Token parseLiteralListOrMapOrFunction(Token token) {
2207 Token constKeyword = null; 2258 Token constKeyword = null;
2208 if (optional('const', token)) { 2259 if (optional('const', token)) {
2209 constKeyword = token; 2260 constKeyword = token;
2210 token = token.next; 2261 token = token.next;
2211 } 2262 }
2212 token = parseTypeArgumentsOpt(token); 2263 if (enableGenericMethodSyntax &&
2264 constKeyword == null &&
2265 optional('<', token) &&
2266 token is BeginGroupToken &&
2267 token.endGroup != null &&
2268 identical(token.endGroup.next.kind, OPEN_PAREN_TOKEN)) {
2269 token = parseTypeVariablesOpt(token);
2270 } else {
2271 // [parseLiteralListOrMapOrFunction] is only called when [token] is one
2272 // of `<`, '{', `[`, so we are not looking at a non-generic literal
2273 // function, so we are looking at a map or list literal, and they may
2274 // or may not have a `<..>` part, but if it is present it contains type
2275 // arguments.
2276 token = parseTypeArgumentsOpt(token);
2277 }
2213 Token beginToken = token; 2278 Token beginToken = token;
2214 int count = 0; 2279 int count = 0;
2215 if (optional('{', token)) { 2280 if (optional('{', token)) {
2216 bool old = mayParseFunctionExpressions; 2281 bool old = mayParseFunctionExpressions;
2217 mayParseFunctionExpressions = true; 2282 mayParseFunctionExpressions = true;
2218 do { 2283 do {
2219 if (optional('}', token.next)) { 2284 if (optional('}', token.next)) {
2220 token = token.next; 2285 token = token.next;
2221 break; 2286 break;
2222 } 2287 }
(...skipping 13 matching lines...) Expand all
2236 } 2301 }
2237 token = parseExpression(token.next); 2302 token = parseExpression(token.next);
2238 ++count; 2303 ++count;
2239 } while (optional(',', token)); 2304 } while (optional(',', token));
2240 mayParseFunctionExpressions = old; 2305 mayParseFunctionExpressions = old;
2241 listener.handleLiteralList(count, beginToken, constKeyword, token); 2306 listener.handleLiteralList(count, beginToken, constKeyword, token);
2242 return expect(']', token); 2307 return expect(']', token);
2243 } else if (optional('[]', token)) { 2308 } else if (optional('[]', token)) {
2244 listener.handleLiteralList(0, token, constKeyword, token); 2309 listener.handleLiteralList(0, token, constKeyword, token);
2245 return token.next; 2310 return token.next;
2246 } else { 2311 } else if (optional('(',token)) {
2247 listener.unexpected(token); 2312 BeginGroupToken beginGroup = token;
2248 return null; 2313 if (beginGroup.endGroup != null) {
2314 Token nextToken = beginGroup.endGroup.next;
2315 int kind = nextToken.kind;
2316 if (identical(kind, FUNCTION_TOKEN) ||
2317 identical(kind, OPEN_CURLY_BRACKET_TOKEN) ||
2318 (identical(kind, KEYWORD_TOKEN) &&
2319 (nextToken.value == 'async' || nextToken.value == 'sync'))) {
2320 return parseUnnamedFunction(token);
2321 }
2322 // Fall through.
2323 }
2249 } 2324 }
2325 listener.unexpected(token);
2326 return null;
2250 } 2327 }
2251 2328
2252 Token parseMapLiteralEntry(Token token) { 2329 Token parseMapLiteralEntry(Token token) {
2253 listener.beginLiteralMapEntry(token); 2330 listener.beginLiteralMapEntry(token);
2254 // Assume the listener rejects non-string keys. 2331 // Assume the listener rejects non-string keys.
2255 token = parseExpression(token); 2332 token = parseExpression(token);
2256 Token colon = token; 2333 Token colon = token;
2257 token = expect(':', token); 2334 token = expect(':', token);
2258 token = parseExpression(token); 2335 token = parseExpression(token);
2259 listener.endLiteralMapEntry(colon, token); 2336 listener.endLiteralMapEntry(colon, token);
2260 return token; 2337 return token;
2261 } 2338 }
2262 2339
2263 Token parseSendOrFunctionLiteral(Token token) { 2340 Token parseSendOrFunctionLiteral(Token token) {
2264 if (!mayParseFunctionExpressions) return parseSend(token); 2341 if (!mayParseFunctionExpressions) return parseSend(token);
2265 Token peek = peekAfterIfType(token); 2342 Token peek = peekAfterIfType(token);
2266 if (peek != null && 2343 if (peek != null &&
2267 identical(peek.kind, IDENTIFIER_TOKEN) && 2344 identical(peek.kind, IDENTIFIER_TOKEN) &&
2268 isFunctionDeclaration(peek.next)) { 2345 isFunctionDeclaration(peek.next)) {
2269 return parseFunctionExpression(token); 2346 return parseFunctionExpression(token);
2270 } else if (isFunctionDeclaration(token.next)) { 2347 } else if (isFunctionDeclaration(token.next)) {
2271 return parseFunctionExpression(token); 2348 return parseFunctionExpression(token);
2272 } else { 2349 } else {
2273 return parseSend(token); 2350 return parseSend(token);
2274 } 2351 }
2275 } 2352 }
2276 2353
2277 bool isFunctionDeclaration(Token token) { 2354 bool isFunctionDeclaration(Token token) {
2355 if (enableGenericMethodSyntax && optional('<', token)) {
2356 BeginGroupToken begin = token;
2357 if (begin.endGroup == null) return false;
2358 token = begin.endGroup.next;
2359 }
2278 if (optional('(', token)) { 2360 if (optional('(', token)) {
2279 BeginGroupToken begin = token; 2361 BeginGroupToken begin = token;
2362 // TODO(eernst): Check this, looks like an NPE with unbalanced parens.
2280 String afterParens = begin.endGroup.next.stringValue; 2363 String afterParens = begin.endGroup.next.stringValue;
2281 if (identical(afterParens, '{') || 2364 if (identical(afterParens, '{') ||
2282 identical(afterParens, '=>') || 2365 identical(afterParens, '=>') ||
2283 identical(afterParens, 'async') || 2366 identical(afterParens, 'async') ||
2284 identical(afterParens, 'sync')) { 2367 identical(afterParens, 'sync')) {
2285 return true; 2368 return true;
2286 } 2369 }
2287 } 2370 }
2288 return false; 2371 return false;
2289 } 2372 }
(...skipping 18 matching lines...) Expand all
2308 } 2391 }
2309 2392
2310 Token parseConstExpression(Token token) { 2393 Token parseConstExpression(Token token) {
2311 Token constKeyword = token; 2394 Token constKeyword = token;
2312 token = expect('const', token); 2395 token = expect('const', token);
2313 final String value = token.stringValue; 2396 final String value = token.stringValue;
2314 if ((identical(value, '<')) || 2397 if ((identical(value, '<')) ||
2315 (identical(value, '[')) || 2398 (identical(value, '[')) ||
2316 (identical(value, '[]')) || 2399 (identical(value, '[]')) ||
2317 (identical(value, '{'))) { 2400 (identical(value, '{'))) {
2318 return parseLiteralListOrMap(constKeyword); 2401 return parseLiteralListOrMapOrFunction(constKeyword);
2319 } 2402 }
2320 token = parseConstructorReference(token); 2403 token = parseConstructorReference(token);
2321 token = parseRequiredArguments(token); 2404 token = parseRequiredArguments(token);
2322 listener.handleConstExpression(constKeyword); 2405 listener.handleConstExpression(constKeyword);
2323 return token; 2406 return token;
2324 } 2407 }
2325 2408
2326 Token parseLiteralInt(Token token) { 2409 Token parseLiteralInt(Token token) {
2327 listener.handleLiteralInt(token); 2410 listener.handleLiteralInt(token);
2328 return token.next; 2411 return token.next;
(...skipping 532 matching lines...) Expand 10 before | Expand all | Expand 10 after
2861 } 2944 }
2862 listener.handleContinueStatement(hasTarget, continueKeyword, token); 2945 listener.handleContinueStatement(hasTarget, continueKeyword, token);
2863 return expectSemicolon(token); 2946 return expectSemicolon(token);
2864 } 2947 }
2865 2948
2866 Token parseEmptyStatement(Token token) { 2949 Token parseEmptyStatement(Token token) {
2867 listener.handleEmptyStatement(token); 2950 listener.handleEmptyStatement(token);
2868 return expectSemicolon(token); 2951 return expectSemicolon(token);
2869 } 2952 }
2870 } 2953 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/parser/node_listener.dart ('k') | pkg/compiler/lib/src/scanner/array_based_scanner.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698