| ... | ... | @@ -1309,9 +1309,8 @@ const Parser = struct { |
| 1309 | 1309 | return expr; |
| 1310 | 1310 | } |
| 1311 | 1311 | |
| 1312 | | /// Expr <- BoolOrExpr |
| 1313 | 1312 | fn parseExpr(p: *Parser) Error!Node.Index { |
| 1314 | | return p.parseBoolOrExpr(); |
| 1313 | return p.parseExprPrecedence(0); |
| 1315 | 1314 | } |
| 1316 | 1315 | |
| 1317 | 1316 | fn expectExpr(p: *Parser) Error!Node.Index { |
| ... | ... | @@ -1323,263 +1322,100 @@ const Parser = struct { |
| 1323 | 1322 | } |
| 1324 | 1323 | } |
| 1325 | 1324 | |
| 1326 | | /// BoolOrExpr <- BoolAndExpr (KEYWORD_or BoolAndExpr)* |
| 1327 | | fn parseBoolOrExpr(p: *Parser) Error!Node.Index { |
| 1328 | | var res = try p.parseBoolAndExpr(); |
| 1329 | | if (res == 0) return null_node; |
| 1325 | const Assoc = enum { |
| 1326 | left, |
| 1327 | none, |
| 1328 | }; |
| 1330 | 1329 | |
| 1331 | | while (true) { |
| 1332 | | switch (p.token_tags[p.tok_i]) { |
| 1333 | | .keyword_or => { |
| 1334 | | const or_token = p.nextToken(); |
| 1335 | | const rhs = try p.parseBoolAndExpr(); |
| 1336 | | if (rhs == 0) { |
| 1337 | | return p.fail(.invalid_token); |
| 1338 | | } |
| 1339 | | res = try p.addNode(.{ |
| 1340 | | .tag = .bool_or, |
| 1341 | | .main_token = or_token, |
| 1342 | | .data = .{ |
| 1343 | | .lhs = res, |
| 1344 | | .rhs = rhs, |
| 1345 | | }, |
| 1346 | | }); |
| 1347 | | }, |
| 1348 | | else => return res, |
| 1349 | | } |
| 1350 | | } |
| 1351 | | } |
| 1330 | const OperInfo = struct { |
| 1331 | prec: i8, |
| 1332 | tag: Node.Tag, |
| 1333 | assoc: Assoc = Assoc.left, |
| 1334 | }; |
| 1352 | 1335 | |
| 1353 | | /// BoolAndExpr <- CompareExpr (KEYWORD_and CompareExpr)* |
| 1354 | | fn parseBoolAndExpr(p: *Parser) !Node.Index { |
| 1355 | | var res = try p.parseCompareExpr(); |
| 1356 | | if (res == 0) return null_node; |
| 1336 | // A table of binary operator information. Higher precedence numbers are |
| 1337 | // stickier. All operators at the same precedence level should have the same |
| 1338 | // associativity. |
| 1339 | const operTable = std.enums.directEnumArrayDefault(Token.Tag, OperInfo, .{ .prec = -1, .tag = Node.Tag.root }, 0, .{ |
| 1340 | .keyword_or = .{ .prec = 10, .tag = .bool_or }, |
| 1341 | |
| 1342 | .keyword_and = .{ .prec = 20, .tag = .bool_and }, |
| 1343 | .invalid_ampersands = .{ .prec = 20, .tag = .bool_and }, |
| 1344 | |
| 1345 | .equal_equal = .{ .prec = 30, .tag = .equal_equal, .assoc = Assoc.none }, |
| 1346 | .bang_equal = .{ .prec = 30, .tag = .bang_equal, .assoc = Assoc.none }, |
| 1347 | .angle_bracket_left = .{ .prec = 30, .tag = .less_than, .assoc = Assoc.none }, |
| 1348 | .angle_bracket_right = .{ .prec = 30, .tag = .greater_than, .assoc = Assoc.none }, |
| 1349 | .angle_bracket_left_equal = .{ .prec = 30, .tag = .less_or_equal, .assoc = Assoc.none }, |
| 1350 | .angle_bracket_right_equal = .{ .prec = 30, .tag = .greater_or_equal, .assoc = Assoc.none }, |
| 1351 | |
| 1352 | .ampersand = .{ .prec = 40, .tag = .bit_and }, |
| 1353 | .caret = .{ .prec = 40, .tag = .bit_xor }, |
| 1354 | .pipe = .{ .prec = 40, .tag = .bit_or }, |
| 1355 | .keyword_orelse = .{ .prec = 40, .tag = .@"orelse" }, |
| 1356 | .keyword_catch = .{ .prec = 40, .tag = .@"catch" }, |
| 1357 | |
| 1358 | .angle_bracket_angle_bracket_left = .{ .prec = 50, .tag = .bit_shift_left }, |
| 1359 | .angle_bracket_angle_bracket_right = .{ .prec = 50, .tag = .bit_shift_right }, |
| 1360 | |
| 1361 | .plus = .{ .prec = 60, .tag = .add }, |
| 1362 | .minus = .{ .prec = 60, .tag = .sub }, |
| 1363 | .plus_plus = .{ .prec = 60, .tag = .array_cat }, |
| 1364 | .plus_percent = .{ .prec = 60, .tag = .add_wrap }, |
| 1365 | .minus_percent = .{ .prec = 60, .tag = .sub_wrap }, |
| 1366 | |
| 1367 | .pipe_pipe = .{ .prec = 70, .tag = .merge_error_sets }, |
| 1368 | .asterisk = .{ .prec = 70, .tag = .mul }, |
| 1369 | .slash = .{ .prec = 70, .tag = .div }, |
| 1370 | .percent = .{ .prec = 70, .tag = .mod }, |
| 1371 | .asterisk_asterisk = .{ .prec = 70, .tag = .array_mult }, |
| 1372 | .asterisk_percent = .{ .prec = 70, .tag = .mul_wrap }, |
| 1373 | }); |
| 1357 | 1374 | |
| 1358 | | while (true) { |
| 1359 | | switch (p.token_tags[p.tok_i]) { |
| 1360 | | .keyword_and => { |
| 1361 | | const and_token = p.nextToken(); |
| 1362 | | const rhs = try p.parseCompareExpr(); |
| 1363 | | if (rhs == 0) { |
| 1364 | | return p.fail(.invalid_token); |
| 1365 | | } |
| 1366 | | res = try p.addNode(.{ |
| 1367 | | .tag = .bool_and, |
| 1368 | | .main_token = and_token, |
| 1369 | | .data = .{ |
| 1370 | | .lhs = res, |
| 1371 | | .rhs = rhs, |
| 1372 | | }, |
| 1373 | | }); |
| 1374 | | }, |
| 1375 | | .invalid_ampersands => { |
| 1376 | | try p.warn(.invalid_and); |
| 1377 | | p.tok_i += 1; |
| 1378 | | return p.parseCompareExpr(); |
| 1379 | | }, |
| 1380 | | else => return res, |
| 1381 | | } |
| 1375 | fn parseExprPrecedence(p: *Parser, min_prec: i32) Error!Node.Index { |
| 1376 | var node = try p.parsePrefixExpr(); |
| 1377 | if (node == 0) { |
| 1378 | return null_node; |
| 1382 | 1379 | } |
| 1383 | | } |
| 1384 | 1380 | |
| 1385 | | /// CompareExpr <- BitwiseExpr (CompareOp BitwiseExpr)? |
| 1386 | | /// CompareOp |
| 1387 | | /// <- EQUALEQUAL |
| 1388 | | /// / EXCLAMATIONMARKEQUAL |
| 1389 | | /// / LARROW |
| 1390 | | /// / RARROW |
| 1391 | | /// / LARROWEQUAL |
| 1392 | | /// / RARROWEQUAL |
| 1393 | | fn parseCompareExpr(p: *Parser) !Node.Index { |
| 1394 | | const expr = try p.parseBitwiseExpr(); |
| 1395 | | if (expr == 0) return null_node; |
| 1396 | | |
| 1397 | | const tag: Node.Tag = switch (p.token_tags[p.tok_i]) { |
| 1398 | | .equal_equal => .equal_equal, |
| 1399 | | .bang_equal => .bang_equal, |
| 1400 | | .angle_bracket_left => .less_than, |
| 1401 | | .angle_bracket_right => .greater_than, |
| 1402 | | .angle_bracket_left_equal => .less_or_equal, |
| 1403 | | .angle_bracket_right_equal => .greater_or_equal, |
| 1404 | | else => return expr, |
| 1405 | | }; |
| 1406 | | return p.addNode(.{ |
| 1407 | | .tag = tag, |
| 1408 | | .main_token = p.nextToken(), |
| 1409 | | .data = .{ |
| 1410 | | .lhs = expr, |
| 1411 | | .rhs = try p.expectBitwiseExpr(), |
| 1412 | | }, |
| 1413 | | }); |
| 1414 | | } |
| 1415 | | |
| 1416 | | /// BitwiseExpr <- BitShiftExpr (BitwiseOp BitShiftExpr)* |
| 1417 | | /// BitwiseOp |
| 1418 | | /// <- AMPERSAND |
| 1419 | | /// / CARET |
| 1420 | | /// / PIPE |
| 1421 | | /// / KEYWORD_orelse |
| 1422 | | /// / KEYWORD_catch Payload? |
| 1423 | | fn parseBitwiseExpr(p: *Parser) !Node.Index { |
| 1424 | | var res = try p.parseBitShiftExpr(); |
| 1425 | | if (res == 0) return null_node; |
| 1381 | var banned_prec: i8 = -1; |
| 1426 | 1382 | |
| 1427 | 1383 | while (true) { |
| 1428 | | const tag: Node.Tag = switch (p.token_tags[p.tok_i]) { |
| 1429 | | .ampersand => .bit_and, |
| 1430 | | .caret => .bit_xor, |
| 1431 | | .pipe => .bit_or, |
| 1432 | | .keyword_orelse => .@"orelse", |
| 1384 | const tok_tag = p.token_tags[p.tok_i]; |
| 1385 | const info = operTable[@intCast(usize, @enumToInt(tok_tag))]; |
| 1386 | if (info.prec < min_prec or info.prec == banned_prec) { |
| 1387 | break; |
| 1388 | } |
| 1389 | const oper_token = p.nextToken(); |
| 1390 | // Special-case handling for "catch" and "&&". |
| 1391 | switch (tok_tag) { |
| 1433 | 1392 | .keyword_catch => { |
| 1434 | | const catch_token = p.nextToken(); |
| 1435 | 1393 | _ = try p.parsePayload(); |
| 1436 | | const rhs = try p.parseBitShiftExpr(); |
| 1437 | | if (rhs == 0) { |
| 1438 | | return p.fail(.invalid_token); |
| 1439 | | } |
| 1440 | | res = try p.addNode(.{ |
| 1441 | | .tag = .@"catch", |
| 1442 | | .main_token = catch_token, |
| 1443 | | .data = .{ |
| 1444 | | .lhs = res, |
| 1445 | | .rhs = rhs, |
| 1446 | | }, |
| 1447 | | }); |
| 1448 | | continue; |
| 1449 | | }, |
| 1450 | | else => return res, |
| 1451 | | }; |
| 1452 | | res = try p.addNode(.{ |
| 1453 | | .tag = tag, |
| 1454 | | .main_token = p.nextToken(), |
| 1455 | | .data = .{ |
| 1456 | | .lhs = res, |
| 1457 | | .rhs = try p.expectBitShiftExpr(), |
| 1458 | 1394 | }, |
| 1459 | | }); |
| 1460 | | } |
| 1461 | | } |
| 1462 | | |
| 1463 | | fn expectBitwiseExpr(p: *Parser) Error!Node.Index { |
| 1464 | | const node = try p.parseBitwiseExpr(); |
| 1465 | | if (node == 0) { |
| 1466 | | return p.fail(.invalid_token); |
| 1467 | | } else { |
| 1468 | | return node; |
| 1469 | | } |
| 1470 | | } |
| 1471 | | |
| 1472 | | /// BitShiftExpr <- AdditionExpr (BitShiftOp AdditionExpr)* |
| 1473 | | /// BitShiftOp |
| 1474 | | /// <- LARROW2 |
| 1475 | | /// / RARROW2 |
| 1476 | | fn parseBitShiftExpr(p: *Parser) Error!Node.Index { |
| 1477 | | var res = try p.parseAdditionExpr(); |
| 1478 | | if (res == 0) return null_node; |
| 1479 | | |
| 1480 | | while (true) { |
| 1481 | | const tag: Node.Tag = switch (p.token_tags[p.tok_i]) { |
| 1482 | | .angle_bracket_angle_bracket_left => .bit_shift_left, |
| 1483 | | .angle_bracket_angle_bracket_right => .bit_shift_right, |
| 1484 | | else => return res, |
| 1485 | | }; |
| 1486 | | res = try p.addNode(.{ |
| 1487 | | .tag = tag, |
| 1488 | | .main_token = p.nextToken(), |
| 1489 | | .data = .{ |
| 1490 | | .lhs = res, |
| 1491 | | .rhs = try p.expectAdditionExpr(), |
| 1395 | .invalid_ampersands => { |
| 1396 | try p.warn(.invalid_and); |
| 1492 | 1397 | }, |
| 1493 | | }); |
| 1494 | | } |
| 1495 | | } |
| 1496 | | |
| 1497 | | fn expectBitShiftExpr(p: *Parser) Error!Node.Index { |
| 1498 | | const node = try p.parseBitShiftExpr(); |
| 1499 | | if (node == 0) { |
| 1500 | | return p.fail(.invalid_token); |
| 1501 | | } else { |
| 1502 | | return node; |
| 1503 | | } |
| 1504 | | } |
| 1505 | | |
| 1506 | | /// AdditionExpr <- MultiplyExpr (AdditionOp MultiplyExpr)* |
| 1507 | | /// AdditionOp |
| 1508 | | /// <- PLUS |
| 1509 | | /// / MINUS |
| 1510 | | /// / PLUS2 |
| 1511 | | /// / PLUSPERCENT |
| 1512 | | /// / MINUSPERCENT |
| 1513 | | fn parseAdditionExpr(p: *Parser) Error!Node.Index { |
| 1514 | | var res = try p.parseMultiplyExpr(); |
| 1515 | | if (res == 0) return null_node; |
| 1398 | else => {}, |
| 1399 | } |
| 1400 | const rhs = try p.parseExprPrecedence(info.prec + 1); |
| 1401 | if (rhs == 0) { |
| 1402 | return p.fail(.invalid_token); |
| 1403 | } |
| 1516 | 1404 | |
| 1517 | | while (true) { |
| 1518 | | const tag: Node.Tag = switch (p.token_tags[p.tok_i]) { |
| 1519 | | .plus => .add, |
| 1520 | | .minus => .sub, |
| 1521 | | .plus_plus => .array_cat, |
| 1522 | | .plus_percent => .add_wrap, |
| 1523 | | .minus_percent => .sub_wrap, |
| 1524 | | else => return res, |
| 1525 | | }; |
| 1526 | | res = try p.addNode(.{ |
| 1527 | | .tag = tag, |
| 1528 | | .main_token = p.nextToken(), |
| 1405 | node = try p.addNode(.{ |
| 1406 | .tag = info.tag, |
| 1407 | .main_token = oper_token, |
| 1529 | 1408 | .data = .{ |
| 1530 | | .lhs = res, |
| 1531 | | .rhs = try p.expectMultiplyExpr(), |
| 1409 | .lhs = node, |
| 1410 | .rhs = rhs, |
| 1532 | 1411 | }, |
| 1533 | 1412 | }); |
| 1534 | | } |
| 1535 | | } |
| 1536 | 1413 | |
| 1537 | | fn expectAdditionExpr(p: *Parser) Error!Node.Index { |
| 1538 | | const node = try p.parseAdditionExpr(); |
| 1539 | | if (node == 0) { |
| 1540 | | return p.fail(.invalid_token); |
| 1541 | | } |
| 1542 | | return node; |
| 1543 | | } |
| 1544 | | |
| 1545 | | /// MultiplyExpr <- PrefixExpr (MultiplyOp PrefixExpr)* |
| 1546 | | /// MultiplyOp |
| 1547 | | /// <- PIPE2 |
| 1548 | | /// / ASTERISK |
| 1549 | | /// / SLASH |
| 1550 | | /// / PERCENT |
| 1551 | | /// / ASTERISK2 |
| 1552 | | /// / ASTERISKPERCENT |
| 1553 | | fn parseMultiplyExpr(p: *Parser) Error!Node.Index { |
| 1554 | | var res = try p.parsePrefixExpr(); |
| 1555 | | if (res == 0) return null_node; |
| 1556 | | |
| 1557 | | while (true) { |
| 1558 | | const tag: Node.Tag = switch (p.token_tags[p.tok_i]) { |
| 1559 | | .pipe_pipe => .merge_error_sets, |
| 1560 | | .asterisk => .mul, |
| 1561 | | .slash => .div, |
| 1562 | | .percent => .mod, |
| 1563 | | .asterisk_asterisk => .array_mult, |
| 1564 | | .asterisk_percent => .mul_wrap, |
| 1565 | | else => return res, |
| 1566 | | }; |
| 1567 | | res = try p.addNode(.{ |
| 1568 | | .tag = tag, |
| 1569 | | .main_token = p.nextToken(), |
| 1570 | | .data = .{ |
| 1571 | | .lhs = res, |
| 1572 | | .rhs = try p.expectPrefixExpr(), |
| 1573 | | }, |
| 1574 | | }); |
| 1414 | if (info.assoc == Assoc.none) { |
| 1415 | banned_prec = info.prec; |
| 1416 | } |
| 1575 | 1417 | } |
| 1576 | | } |
| 1577 | 1418 | |
| 1578 | | fn expectMultiplyExpr(p: *Parser) Error!Node.Index { |
| 1579 | | const node = try p.parseMultiplyExpr(); |
| 1580 | | if (node == 0) { |
| 1581 | | return p.fail(.invalid_token); |
| 1582 | | } |
| 1583 | 1419 | return node; |
| 1584 | 1420 | } |
| 1585 | 1421 | |