|
1181 | 1181 | };
|
1182 | 1182 | }
|
1183 | 1183 |
|
| 1184 | + /** |
| 1185 | + * Matches a template string |
| 1186 | + * |
| 1187 | + * @return {Complexion~matcher} |
| 1188 | + */ |
| 1189 | + function matchTemplateString() { |
| 1190 | + function movePastEscape(str, offset) { |
| 1191 | + var c; |
| 1192 | + |
| 1193 | + c = str.charAt(offset); |
| 1194 | + |
| 1195 | + // You can't escape a line terminator |
| 1196 | + if (isLineTerminator(c)) { |
| 1197 | + return 0; |
| 1198 | + } |
| 1199 | + |
| 1200 | + if (c >= '4' && c <= '7') { |
| 1201 | + // Octal numbers that can only be two digits |
| 1202 | + c = str.charAt(offset + 1); |
| 1203 | + |
| 1204 | + if (c >= '0' && c <= '7') { |
| 1205 | + return 2; |
| 1206 | + } |
| 1207 | + } else if (c >= '0' && c <= '3') { |
| 1208 | + // Octal numbers that can be three digits |
| 1209 | + c = str.charAt(offset + 1); |
| 1210 | + |
| 1211 | + if (c >= '0' && c <= '7') { |
| 1212 | + c = str.charAt(offset + 2); |
| 1213 | + |
| 1214 | + if (c >= '0' && c <= '7') { |
| 1215 | + return 3; |
| 1216 | + } |
| 1217 | + |
| 1218 | + return 2; |
| 1219 | + } |
| 1220 | + } else if (c === 'x') { |
| 1221 | + // Hex |
| 1222 | + if (isHex(str.charAt(offset + 1)) && isHex(str.charAt(offset + 2))) { |
| 1223 | + return 3; |
| 1224 | + } |
| 1225 | + } else if (c === 'u') { |
| 1226 | + // Unicode |
| 1227 | + if (isHex(str.charAt(offset + 1)) && isHex(str.charAt(offset + 2)) && isHex(str.charAt(offset + 3)) && isHex(str.charAt(offset + 4))) { |
| 1228 | + return 5; |
| 1229 | + } |
| 1230 | + } |
| 1231 | + |
| 1232 | + // We are just escaping a single character |
| 1233 | + return 1; |
| 1234 | + } |
| 1235 | + |
| 1236 | + return function (str, offset) { |
| 1237 | + var c, checkId, inId, len, quote; |
| 1238 | + |
| 1239 | + inId = false; |
| 1240 | + checkId = false; |
| 1241 | + quote = str.charAt(offset); |
| 1242 | + |
| 1243 | + // It must start with single or double quotes |
| 1244 | + if (quote !== '`') { |
| 1245 | + return null; |
| 1246 | + } |
| 1247 | + |
| 1248 | + len = 1; |
| 1249 | + c = str.charAt(offset + len); |
| 1250 | + |
| 1251 | + // Strings must not contain CR, LF, LS, nor PS |
| 1252 | + while (c && c !== quote && !isLineTerminator(c)) { |
| 1253 | + len += 1; |
| 1254 | + |
| 1255 | + if (c === "\\") { |
| 1256 | + len += movePastEscape(str, offset + len); |
| 1257 | + } |
| 1258 | + |
| 1259 | + if (checkId && c === "{") { |
| 1260 | + checkId = false; |
| 1261 | + inId = true; |
| 1262 | + } |
| 1263 | + |
| 1264 | + if (inId && c === '}') { |
| 1265 | + inId = false; |
| 1266 | + } |
| 1267 | + |
| 1268 | + if (c === "$") { |
| 1269 | + checkId = true; |
| 1270 | + } |
| 1271 | + |
| 1272 | + c = str.charAt(offset + len); |
| 1273 | + } |
| 1274 | + |
| 1275 | + if (c !== quote || inId) { |
| 1276 | + return null; |
| 1277 | + } |
| 1278 | + |
| 1279 | + return str.substr(offset, len + 1); |
| 1280 | + }; |
| 1281 | + } |
| 1282 | + |
1184 | 1283 |
|
1185 | 1284 | /**
|
1186 | 1285 | * Matches any character
|
|
1328 | 1427 | add('LINE_TERMINATOR', matchLineTerminator); // Can set implicitSemicolonFlag
|
1329 | 1428 | add('KEYWORD', matchKeyword); // Uses keywordFromIdentifierName
|
1330 | 1429 | add('STRING_LITERAL', matchStringLiteral);
|
| 1430 | + add('TEMPLATE_STRING', matchTemplateString); |
1331 | 1431 | add('SINGLE_LINE_COMMENT', matchSingleLineComment);
|
1332 | 1432 | add('BOOLEAN_LITERAL', matchBooleanLiteral); // Uses keywordFromIdentifierName
|
1333 | 1433 | add('NULL_LITERAL', matchNullLiteral); // Uses keywordFromIdentifierName
|
|
0 commit comments