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

Side by Side Diff: frog/parser.dart

Issue 9121025: cleanup to Value - fix for StringEscapesTest (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 11 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 | Annotate | Revision Log
OLDNEW
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 // TODO(jimhug): Error recovery needs major work! 5 // TODO(jimhug): Error recovery needs major work!
6 /** 6 /**
7 * A simple recursive descent parser for the dart language. 7 * A simple recursive descent parser for the dart language.
8 * 8 *
9 * This parser is designed to be more permissive than the official 9 * This parser is designed to be more permissive than the official
10 * Dart grammar. It is expected that many grammar errors would be 10 * Dart grammar. It is expected that many grammar errors would be
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
61 _afterParens = <Token>[]; 61 _afterParens = <Token>[];
62 } 62 }
63 63
64 /** Generate an error if [source] has not been completely consumed. */ 64 /** Generate an error if [source] has not been completely consumed. */
65 void checkEndOfFile() { 65 void checkEndOfFile() {
66 _eat(TokenKind.END_OF_FILE); 66 _eat(TokenKind.END_OF_FILE);
67 } 67 }
68 68
69 /** Guard to break out of parser when an unexpected end of file is found. */ 69 /** Guard to break out of parser when an unexpected end of file is found. */
70 bool isPrematureEndOfFile() { 70 bool isPrematureEndOfFile() {
71 if (throwOnIncomplete && _maybeEat(TokenKind.END_OF_FILE) || 71 if (throwOnIncomplete && _maybeEat(TokenKind.END_OF_FILE)) {
72 _maybeEat(TokenKind.INCOMPLETE_MULTILINE_STRING_DQ) ||
Jennifer Messerly 2012/01/09 20:16:26 I think this was REPL support code that had found
jimhug 2012/01/09 21:19:05 This was originally my code intended to handle sin
73 _maybeEat(TokenKind.INCOMPLETE_MULTILINE_STRING_SQ)) {
74 throw new IncompleteSourceException(_previousToken); 72 throw new IncompleteSourceException(_previousToken);
75 } else if (_maybeEat(TokenKind.END_OF_FILE)) { 73 } else if (_maybeEat(TokenKind.END_OF_FILE)) {
76 _error('unexpected end of file', _peekToken.span); 74 _error('unexpected end of file', _peekToken.span);
77 return true; 75 return true;
78 } else { 76 } else {
79 return false; 77 return false;
80 } 78 }
81 } 79 }
82 80
83 /** 81 /**
(...skipping 957 matching lines...) Expand 10 before | Expand all | Expand 10 after
1041 return finishPostfixExpression( 1039 return finishPostfixExpression(
1042 new CallExpression(expr, args, _makeSpan(expr.span.start))); 1040 new CallExpression(expr, args, _makeSpan(expr.span.start)));
1043 } 1041 }
1044 } 1042 }
1045 1043
1046 /** Checks if the given expression is a binary op of the given kind. */ 1044 /** Checks if the given expression is a binary op of the given kind. */
1047 _isBin(expr, kind) { 1045 _isBin(expr, kind) {
1048 return expr is BinaryExpression && expr.op.kind == kind; 1046 return expr is BinaryExpression && expr.op.kind == kind;
1049 } 1047 }
1050 1048
1051 _boolTypeRef(SourceSpan span) { 1049 _makeLiteral(Value value) {
1052 return new TypeReference(span, world.nonNullBool); 1050 return new LiteralExpression(value, value.span);
1053 }
1054
1055 _intTypeRef(SourceSpan span) {
1056 return new TypeReference(span, world.intType);
1057 }
1058
1059 _doubleTypeRef(SourceSpan span) {
1060 return new TypeReference(span, world.doubleType);
1061 }
1062
1063 _stringTypeRef(SourceSpan span) {
1064 return new TypeReference(span, world.stringType);
1065 } 1051 }
1066 1052
1067 primary() { 1053 primary() {
1068 int start = _peekToken.start; 1054 int start = _peekToken.start;
1069 switch (_peek()) { 1055 switch (_peek()) {
1070 case TokenKind.THIS: 1056 case TokenKind.THIS:
1071 _eat(TokenKind.THIS); 1057 _eat(TokenKind.THIS);
1072 return new ThisExpression(_makeSpan(start)); 1058 return new ThisExpression(_makeSpan(start));
1073 1059
1074 case TokenKind.SUPER: 1060 case TokenKind.SUPER:
(...skipping 21 matching lines...) Expand all
1096 1082
1097 case TokenKind.LBRACK: 1083 case TokenKind.LBRACK:
1098 case TokenKind.INDEX: 1084 case TokenKind.INDEX:
1099 return finishListLiteral(start, false, null); 1085 return finishListLiteral(start, false, null);
1100 case TokenKind.LBRACE: 1086 case TokenKind.LBRACE:
1101 return finishMapLiteral(start, false, null); 1087 return finishMapLiteral(start, false, null);
1102 1088
1103 // Literals 1089 // Literals
1104 case TokenKind.NULL: 1090 case TokenKind.NULL:
1105 _eat(TokenKind.NULL); 1091 _eat(TokenKind.NULL);
1106 return new NullExpression(_makeSpan(start)); 1092 return _makeLiteral(Value.fromNull(_makeSpan(start)));
1107 1093
1108 // TODO(jimhug): Make Literal creation less wasteful - no dup span/text. 1094 // TODO(jimhug): Make Literal creation less wasteful - no dup span/text.
1109 case TokenKind.TRUE: 1095 case TokenKind.TRUE:
1110 _eat(TokenKind.TRUE); 1096 _eat(TokenKind.TRUE);
1111 return new LiteralExpression(true, _boolTypeRef(_makeSpan(start)), 1097 return _makeLiteral(Value.fromBool(true, _makeSpan(start)));
1112 'true', _makeSpan(start));
1113 1098
1114 case TokenKind.FALSE: 1099 case TokenKind.FALSE:
1115 _eat(TokenKind.FALSE); 1100 _eat(TokenKind.FALSE);
1116 return new LiteralExpression(false,_boolTypeRef(_makeSpan(start)), 1101 return _makeLiteral(Value.fromBool(false, _makeSpan(start)));
1117 'false', _makeSpan(start));
1118 1102
1119 case TokenKind.HEX_INTEGER: 1103 case TokenKind.HEX_INTEGER:
1120 var t = _next(); 1104 var t = _next();
1121 // Remove the 0x or 0X before parsing the hex number. 1105 return _makeLiteral(Value.fromInt(t.value, t.span));
1122 return new LiteralExpression(parseHex(t.text.substring(2)),
1123 _intTypeRef(_makeSpan(start)), t.text, _makeSpan(start));
1124 1106
1125 case TokenKind.INTEGER: 1107 case TokenKind.INTEGER:
1126 var t = _next(); 1108 var t = _next();
1127 return new LiteralExpression(Math.parseInt(t.text), 1109 return _makeLiteral(Value.fromInt(Math.parseInt(t.text), t.span));
1128 _intTypeRef(_makeSpan(start)), t.text, _makeSpan(start));
1129 1110
1130 case TokenKind.DOUBLE: 1111 case TokenKind.DOUBLE:
1131 var t = _next(); 1112 var t = _next();
1132 return new LiteralExpression(Math.parseDouble(t.text), 1113 return _makeLiteral(
1133 _doubleTypeRef(_makeSpan(start)), t.text, _makeSpan(start)); 1114 Value.fromDouble(Math.parseDouble(t.text), t.span));
1134 1115
1135 case TokenKind.STRING: 1116 case TokenKind.STRING:
1136 return stringLiteralExpr(); 1117 var t = _next();
1118 return _makeLiteral(Value.fromString(t.value, t.span));
1137 1119
1138 case TokenKind.INCOMPLETE_STRING: 1120 case TokenKind.STRING_PART:
1139 return stringInterpolation(); 1121 return stringInterpolation();
1140 1122
1141 case TokenKind.LT: 1123 case TokenKind.LT:
1142 return finishTypedLiteral(start, false); 1124 return finishTypedLiteral(start, false);
1143 1125
1144 case TokenKind.VOID: 1126 case TokenKind.VOID:
1145 case TokenKind.VAR: 1127 case TokenKind.VAR:
1146 case TokenKind.FINAL: 1128 case TokenKind.FINAL:
1147 return declaredIdentifier(false); 1129 return declaredIdentifier(false);
1148 1130
1149 default: 1131 default:
1150 if (!_peekIdentifier()) { 1132 if (!_peekIdentifier()) {
1151 // TODO(jimhug): Better error message. 1133 // TODO(jimhug): Better error message.
1152 _errorExpected('expression'); 1134 _errorExpected('expression');
1153 } 1135 }
1154 return new VarExpression(identifier(), _makeSpan(start)); 1136 return new VarExpression(identifier(), _makeSpan(start));
1155 } 1137 }
1156 } 1138 }
1157 1139
1158 stringInterpolation() { 1140 stringInterpolation() {
1159 int start = _peekToken.start; 1141 int start = _peekToken.start;
1160 var lits = []; 1142 var pieces = new List<Expression>();
1161 var startQuote = null, endQuote = null; 1143 var startQuote = null, endQuote = null;
1162 while(_peekKind(TokenKind.INCOMPLETE_STRING)) { 1144 while(_peekKind(TokenKind.STRING_PART)) {
1163 var token = _next(); 1145 var token = _next();
1164 var text = token.text; 1146 pieces.add(_makeLiteral(Value.fromString(token.value, token.span)));
1165 if (startQuote == null) {
1166 if (isMultilineString(text)) {
1167 endQuote = text.substring(0, 3);
1168 // TODO(jmesserly): HACK add a newline to everything that's not
Jennifer Messerly 2012/01/09 20:16:26 --hack;
1169 // the first multiline string, so we don't incorrectly strip off any
1170 // real newlines later in the interpolated string.
1171 startQuote = endQuote + '\n';
1172 } else {
1173 startQuote = endQuote = text[0];
1174 }
1175 text = text.substring(0, text.length-1) + endQuote; // fix trailing $
1176 } else {
1177 text = startQuote + text.substring(0, text.length-1) + endQuote;
1178 }
1179 lits.add(makeStringLiteral(text, token.span));
1180 if (_maybeEat(TokenKind.LBRACE)) { 1147 if (_maybeEat(TokenKind.LBRACE)) {
1181 lits.add(expression()); 1148 pieces.add(expression());
1182 _eat(TokenKind.RBRACE); 1149 _eat(TokenKind.RBRACE);
1183 } else if (_maybeEat(TokenKind.THIS)) { 1150 } else if (_maybeEat(TokenKind.THIS)) {
1184 lits.add(new ThisExpression(_previousToken.span)); 1151 pieces.add(new ThisExpression(_previousToken.span));
1185 } else { 1152 } else {
1186 var id = identifier(); 1153 var id = identifier();
1187 lits.add(new VarExpression(id, id.span)); 1154 pieces.add(new VarExpression(id, id.span));
1188 } 1155 }
1189 } 1156 }
1190 var tok = _next(); 1157 var tok = _next();
1191 if (tok.kind != TokenKind.STRING) { 1158 if (tok.kind != TokenKind.STRING) {
1192 _errorExpected('interpolated string'); 1159 _errorExpected('interpolated string');
1193 } 1160 }
1194 var text = startQuote + tok.text; 1161 pieces.add(_makeLiteral(Value.fromString(tok.value, tok.span)));
1195 lits.add(makeStringLiteral(text, tok.span));
1196 var span = _makeSpan(start); 1162 var span = _makeSpan(start);
1197 return new LiteralExpression(lits, _stringTypeRef(span), '\$\$\$', span); 1163 return new StringInterpExpression(pieces, span);
1198 }
1199
1200 makeStringLiteral(String text, SourceSpan span) {
1201 return new LiteralExpression(text, _stringTypeRef(span), text, span);
1202 }
1203
1204 stringLiteralExpr() {
1205 var token = _next();
1206 return makeStringLiteral(token.text, token.span);
1207 } 1164 }
1208 1165
1209 String maybeStringLiteral() { 1166 String maybeStringLiteral() {
1210 var kind = _peek(); 1167 var kind = _peek();
1211 if (kind == TokenKind.STRING) { 1168 if (kind == TokenKind.STRING) {
1212 return parseStringLiteral(_next().text); 1169 var t = _next();
1170 return t.value;
1213 } else if (kind == TokenKind.STRING_PART) { 1171 } else if (kind == TokenKind.STRING_PART) {
1214 _next(); 1172 _next();
1215 _errorExpected('string literal, but found interpolated string start'); 1173 _errorExpected('string literal, but found interpolated string start');
1216 } else if (kind == TokenKind.INCOMPLETE_STRING) {
1217 _next();
1218 _errorExpected('string literal, but found incomplete string');
1219 } 1174 }
1220 return null; 1175 return null;
1221 } 1176 }
1222 1177
1223 _parenOrLambda() { 1178 _parenOrLambda() {
1224 int start = _peekToken.start; 1179 int start = _peekToken.start;
1225 if (_atClosureParameters()) { 1180 if (_atClosureParameters()) {
1226 var formals = formalParameterList(); 1181 var formals = formalParameterList();
1227 var body = functionBody(true); 1182 var body = functionBody(true);
1228 var func = new FunctionDefinition(null, null, null, formals, null, null, 1183 var func = new FunctionDefinition(null, null, null, formals, null, null,
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
1372 name = _typeAsIdentifier(myType); 1327 name = _typeAsIdentifier(myType);
1373 myType = null; 1328 myType = null;
1374 } else { 1329 } else {
1375 // TODO(jimhug): Where do these errors get handled? 1330 // TODO(jimhug): Where do these errors get handled?
1376 } 1331 }
1377 } 1332 }
1378 } 1333 }
1379 return new DeclaredIdentifier(myType, name, _makeSpan(start)); 1334 return new DeclaredIdentifier(myType, name, _makeSpan(start));
1380 } 1335 }
1381 1336
1382 // TODO(jimhug): Move this to base <= 36 and into shared code.
1383 static int _hexDigit(int c) {
1384 if(c >= 48/*0*/ && c <= 57/*9*/) {
1385 return c - 48;
1386 } else if (c >= 97/*a*/ && c <= 102/*f*/) {
1387 return c - 87;
1388 } else if (c >= 65/*A*/ && c <= 70/*F*/) {
1389 return c - 55;
1390 } else {
1391 return -1;
1392 }
1393 }
1394
1395 static int parseHex(String hex) {
1396 var result = 0;
1397
1398 for (int i = 0; i < hex.length; i++) {
1399 var digit = _hexDigit(hex.charCodeAt(i));
1400 assert(digit != -1);
1401 // Multiply by 16 rather than shift by 4 since that will result in a
1402 // correct value for numbers that exceed the 32 bit precision of JS
1403 // 'integers'.
1404 // TODO: Figure out a better solution to integer truncation. Issue 638.
1405 result = (result * 16) + digit;
1406 }
1407
1408 return result;
1409 }
1410
1411 finishNewExpression(int start, bool isConst) { 1337 finishNewExpression(int start, bool isConst) {
1412 var type = type(); 1338 var type = type();
1413 var name = null; 1339 var name = null;
1414 if (_maybeEat(TokenKind.DOT)) { 1340 if (_maybeEat(TokenKind.DOT)) {
1415 name = identifier(); 1341 name = identifier();
1416 } 1342 }
1417 var args = arguments(); 1343 var args = arguments();
1418 return new NewExpression(isConst, type, name, args, _makeSpan(start)); 1344 return new NewExpression(isConst, type, name, args, _makeSpan(start));
1419 } 1345 }
1420 1346
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after
1651 _error('default values only allowed inside [optional] section'); 1577 _error('default values only allowed inside [optional] section');
1652 } 1578 }
1653 value = expression(); 1579 value = expression();
1654 } else if (_peekKind(TokenKind.LPAREN)) { 1580 } else if (_peekKind(TokenKind.LPAREN)) {
1655 var formals = formalParameterList(); 1581 var formals = formalParameterList();
1656 var func = new FunctionDefinition(null, type, name, formals, 1582 var func = new FunctionDefinition(null, type, name, formals,
1657 null, null, null, _makeSpan(start)); 1583 null, null, null, _makeSpan(start));
1658 type = new FunctionTypeReference(false, func, func.span); 1584 type = new FunctionTypeReference(false, func, func.span);
1659 } 1585 }
1660 if (inOptionalBlock && value == null) { 1586 if (inOptionalBlock && value == null) {
1661 value = new NullExpression(_makeSpan(start)); 1587 value = _makeLiteral(Value.fromNull(_makeSpan(start)));
1662 } 1588 }
1663 1589
1664 return new FormalNode(isThis, isRest, type, name, value, _makeSpan(start)); 1590 return new FormalNode(isThis, isRest, type, name, value, _makeSpan(start));
1665 } 1591 }
1666 1592
1667 formalParameterList() { 1593 formalParameterList() {
1668 _eatLeftParen(); 1594 _eatLeftParen();
1669 var formals = []; 1595 var formals = [];
1670 var inOptionalBlock = false; 1596 var inOptionalBlock = false;
1671 if (!_maybeEat(TokenKind.RPAREN)) { 1597 if (!_maybeEat(TokenKind.RPAREN)) {
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
1773 int _pos = 0; 1699 int _pos = 0;
1774 next() { 1700 next() {
1775 var token = tokens[_pos]; 1701 var token = tokens[_pos];
1776 ++_pos; 1702 ++_pos;
1777 if (_pos == tokens.length) { 1703 if (_pos == tokens.length) {
1778 parser.tokenizer = previousTokenizer; 1704 parser.tokenizer = previousTokenizer;
1779 } 1705 }
1780 return token; 1706 return token;
1781 } 1707 }
1782 } 1708 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698