expr.ha (35424B)
1 // SPDX-License-Identifier: MPL-2.0 2 // (c) Hare authors <https://harelang.org> 3 4 use hare::ast; 5 use hare::lex; 6 use hare::lex::{ltok}; 7 use math; 8 use strings; 9 use types; 10 11 // Parses an expression. 12 export fn expr(lexer: *lex::lexer) (ast::expr | error) = { 13 const loc = lex::mkloc(lexer); 14 15 // All assignment-op tokens 16 const atoks: []ltok = [ 17 ltok::EQUAL, ltok::BANDEQ, ltok::BOREQ, ltok::BXOREQ, 18 ltok::DIVEQ, ltok::LANDEQ, ltok::LOREQ, ltok::LXOREQ, 19 ltok::LSHIFTEQ, ltok::MINUSEQ, ltok::MODEQ, ltok::PLUSEQ, 20 ltok::RSHIFTEQ, ltok::TIMESEQ, 21 ]; 22 23 const ex = match (peek(lexer, ltok::IF, ltok::FOR, ltok::BREAK, 24 ltok::CONTINUE, ltok::RETURN, ltok::YIELD)?) { 25 case void => 26 yield binarithm(lexer, void, 0)?; 27 case let tok: lex::token => 28 yield switch (tok.0) { 29 case ltok::IF => 30 yield if_expr(lexer)?; 31 case ltok::FOR => 32 yield for_expr(lexer)?; 33 case ltok::BREAK, ltok::CONTINUE, ltok::RETURN => 34 yield control(lexer)?; 35 case ltok::YIELD => 36 yield yield_expr(lexer)?; 37 case => abort(); // Invariant 38 }; 39 }; 40 41 const tok = match (try(lexer, atoks...)?) { 42 case let tok: lex::token => 43 yield tok; 44 case => 45 return ex; 46 }; 47 48 const is_obj_selector = match (ex.expr) { 49 case (ast::access_expr | ast::slice_expr) => 50 yield true; 51 case let ex: ast::unarithm_expr => 52 yield ex.op == ast::unarithm_op::DEREF; 53 case => 54 yield false; 55 }; 56 synassert(lex::mkloc(lexer), is_obj_selector, 57 "Expected an object-selector, pointer dereference, or slice for assignment target")?; 58 const ex = ast::assign_expr { 59 op = switch (tok.0) { 60 case ltok::EQUAL => 61 yield void; 62 case ltok::BANDEQ => 63 yield ast::binarithm_op::BAND; 64 case ltok::BOREQ => 65 yield ast::binarithm_op::BOR; 66 case ltok::BXOREQ => 67 yield ast::binarithm_op::BXOR; 68 case ltok::DIVEQ => 69 yield ast::binarithm_op::DIV; 70 case ltok::LANDEQ => 71 yield ast::binarithm_op::LAND; 72 case ltok::LOREQ => 73 yield ast::binarithm_op::LOR; 74 case ltok::LSHIFTEQ => 75 yield ast::binarithm_op::LSHIFT; 76 case ltok::LXOREQ => 77 yield ast::binarithm_op::LXOR; 78 case ltok::MINUSEQ => 79 yield ast::binarithm_op::MINUS; 80 case ltok::MODEQ => 81 yield ast::binarithm_op::MODULO; 82 case ltok::PLUSEQ => 83 yield ast::binarithm_op::PLUS; 84 case ltok::RSHIFTEQ => 85 yield ast::binarithm_op::RSHIFT; 86 case ltok::TIMESEQ => 87 yield ast::binarithm_op::TIMES; 88 case => abort(); // unreachable 89 }, 90 object = alloc(ex)!, 91 value = alloc(expr(lexer)?)!, 92 }; 93 94 return ast::expr { 95 start = loc, 96 end = lex::prevloc(lexer), 97 expr = ex, 98 }; 99 }; 100 101 fn assert_expr(lexer: *lex::lexer, is_static: bool) (ast::expr | error) = { 102 const tok = want(lexer, ltok::ABORT, ltok::ASSERT)?; 103 104 let expr = switch (tok.0) { 105 case ltok::ABORT => 106 want(lexer, ltok::LPAREN)?; 107 const msg: nullable *ast::expr = 108 match (peek(lexer, ltok::RPAREN)?) { 109 case lex::token => 110 yield null; 111 case => 112 yield alloc(expr(lexer)?)!; 113 }; 114 want(lexer, ltok::RPAREN)?; 115 116 yield ast::assert_expr { 117 cond = null, 118 message = msg, 119 is_static = is_static, 120 }; 121 case ltok::ASSERT => 122 want(lexer, ltok::LPAREN)?; 123 const cond: nullable *ast::expr = 124 alloc(expr(lexer)?)!; 125 const msg: nullable *ast::expr = 126 match (try(lexer, ltok::COMMA)?) { 127 case lex::token => 128 yield alloc(expr(lexer)?)!; 129 case => 130 yield null; 131 }; 132 want(lexer, ltok::RPAREN)?; 133 134 yield ast::assert_expr { 135 cond = cond, 136 message = msg, 137 is_static = is_static, 138 }; 139 case => abort(); // unreachable 140 }; 141 142 return ast::expr { 143 start = tok.2, 144 end = lex::prevloc(lexer), 145 expr = expr, 146 }; 147 }; 148 149 fn alloc_expr(lexer: *lex::lexer) (ast::expr | error) = { 150 const start = want(lexer, ltok::ALLOC)?; 151 want(lexer, ltok::LPAREN)?; 152 153 const init = alloc(expr(lexer)?)!; 154 const expr = 155 switch (want(lexer, ltok::COMMA, ltok::ELLIPSIS, ltok::RPAREN)?.0) { 156 case ltok::COMMA => 157 const capacity = alloc(expr(lexer)?)!; 158 want(lexer, ltok::RPAREN)?; 159 yield ast::alloc_expr { 160 init = init, 161 form = ast::alloc_form::COPY, 162 capacity = capacity, 163 }; 164 case ltok::ELLIPSIS => 165 want(lexer, ltok::RPAREN)?; 166 yield ast::alloc_expr { 167 init = init, 168 form = ast::alloc_form::COPY, 169 capacity = null, 170 }; 171 case ltok::RPAREN => 172 yield ast::alloc_expr { 173 init = init, 174 form = ast::alloc_form::OBJECT, 175 capacity = null, 176 }; 177 case => abort(); // unreachable 178 }; 179 180 return ast::expr { 181 start = start.2, 182 end = lex::prevloc(lexer), 183 expr = expr, 184 }; 185 }; 186 187 fn append_insert_expr( 188 lexer: *lex::lexer, 189 is_static: bool, 190 ) (ast::expr | error) = { 191 const tok = want(lexer, ltok::APPEND, ltok::INSERT)?; 192 want(lexer, ltok::LPAREN)?; 193 194 const object = if (tok.0 == ltok::APPEND) objsel(lexer)? 195 else idxexpr(lexer)?; 196 want(lexer, ltok::COMMA)?; 197 const value = expr(lexer)?; 198 199 let length: nullable *ast::expr = null; 200 let variadic = false; 201 match (try(lexer, ltok::COMMA, ltok::ELLIPSIS)?) { 202 case let tok: lex::token => 203 switch (tok.0) { 204 case ltok::COMMA => 205 length = alloc(expr(lexer)?)!; 206 case ltok::ELLIPSIS => 207 variadic = true; 208 case => abort(); 209 }; 210 case void => void; 211 }; 212 want(lexer, ltok::RPAREN)?; 213 214 let expr = ast::append_expr { 215 object = alloc(object)!, 216 value = alloc(value)!, 217 length = length, 218 variadic = variadic, 219 is_static = is_static, 220 }; 221 const expr = if (tok.0 == ltok::INSERT) { 222 yield expr: ast::insert_expr; 223 } else expr; 224 225 return ast::expr { 226 start = tok.2, 227 end = lex::prevloc(lexer), 228 expr = expr, 229 }; 230 }; 231 232 fn measurement(lexer: *lex::lexer) (ast::expr | error) = { 233 const tok = want(lexer, ltok::LEN, ltok::ALIGN, ltok::SIZE, ltok::OFFSET)?; 234 want(lexer, ltok::LPAREN)?; 235 const expr = switch (tok.0) { 236 case ltok::LEN => 237 yield alloc(expr(lexer)?)!: ast::len_expr; 238 case ltok::ALIGN => 239 yield alloc(_type(lexer)?)!: ast::align_expr; 240 case ltok::SIZE => 241 yield alloc(_type(lexer)?)!: ast::size_expr; 242 case ltok::OFFSET => 243 yield alloc(expr(lexer)?)!: ast::offset_expr; 244 case => abort(); // unreachable 245 }; 246 want(lexer, ltok::RPAREN)?; 247 248 return ast::expr { 249 start = tok.2, 250 end = lex::prevloc(lexer), 251 expr = expr, 252 }; 253 }; 254 255 fn binarithm( 256 lexer: *lex::lexer, 257 lvalue: (ast::expr | void), 258 i: int, 259 ) (ast::expr | error) = { 260 // Precedence climbing parser 261 // https://en.wikipedia.org/wiki/Operator-precedence_parser 262 let lvalue = match (lvalue) { 263 case void => 264 yield cast(lexer, void)?; 265 case let expr: ast::expr => 266 yield expr; 267 }; 268 269 let tok = lex::lex(lexer)?; 270 for (let j = precedence(tok); j >= i; j = precedence(tok)) { 271 const op = binop_for_tok(tok); 272 273 let rvalue = cast(lexer, void)?; 274 tok = lex::lex(lexer)?; 275 276 for (let k = precedence(tok); k > j; k = precedence(tok)) { 277 lex::unlex(lexer, tok); 278 rvalue = binarithm(lexer, rvalue, k)?; 279 tok = lex::lex(lexer)?; 280 }; 281 282 const expr = ast::expr { 283 start = lvalue.start, 284 end = lex::prevloc(lexer), 285 expr = ast::binarithm_expr { 286 op = op, 287 lvalue = alloc(lvalue)!, 288 rvalue = alloc(rvalue)!, 289 }, 290 }; 291 lvalue = expr; 292 }; 293 294 lex::unlex(lexer, tok); 295 return lvalue; 296 }; 297 298 fn binding_unpack(lexer: *lex::lexer) (ast::binding_unpack | error) = { 299 let fields: ast::binding_unpack = []; 300 for (true) { 301 const (tok, value, _) = want(lexer, ltok::NAME, 302 ltok::UNDERSCORE)?; 303 if (tok == ltok::UNDERSCORE) { 304 append(fields, void)!; 305 } else { 306 append(fields, value as str)!; 307 }; 308 if (len(fields) == 1) { 309 want(lexer, ltok::COMMA)?; 310 } else { 311 match (try(lexer, ltok::COMMA)?) { 312 case void => break; 313 case lex::token => void; 314 }; 315 }; 316 }; 317 want(lexer, ltok::RPAREN)?; 318 return fields; 319 }; 320 321 fn binding(lexer: *lex::lexer, is_static: bool) (ast::expr | error) = { 322 const loc = lex::mkloc(lexer); 323 const tok = want(lexer, ltok::DEF, ltok::CONST, ltok::LET)?.0; 324 const kind = switch (tok) { 325 case ltok::DEF => 326 assert(!is_static); 327 yield ast::binding_kind::DEF; 328 case ltok::CONST => 329 yield ast::binding_kind::CONST; 330 case ltok::LET => 331 yield ast::binding_kind::LET; 332 case => abort(); // unreachable 333 }; 334 335 let bindings: []ast::binding = []; 336 for (true) { 337 const (tok, value, _) = want(lexer, ltok::NAME, ltok::LPAREN)?; 338 const name = switch (tok) { 339 case ltok::NAME => 340 yield value as str; 341 case ltok::LPAREN => 342 if (kind == ast::binding_kind::DEF) { 343 return syntaxerr(lex::mkloc(lexer), 344 "Can't use tuple unpacking with def"); 345 }; 346 yield binding_unpack(lexer)?; 347 case => abort(); 348 }; 349 const btype: nullable *ast::_type = 350 if (try(lexer, ltok::COLON)? is lex::token) { 351 yield alloc(_type(lexer)?)!; 352 } else null; 353 want(lexer, ltok::EQUAL)?; 354 const init = alloc(expr(lexer)?)!; 355 append(bindings, ast::binding { 356 name = name, 357 _type = btype, 358 init = init, 359 })!; 360 match (try(lexer, ltok::COMMA)?) { 361 case void => break; 362 case lex::token => void; 363 }; 364 }; 365 366 return ast::expr { 367 start = loc, 368 end = lex::prevloc(lexer), 369 expr = ast::binding_expr { 370 is_static = is_static, 371 kind = kind, 372 bindings = bindings, 373 }, 374 }; 375 }; 376 377 fn builtin(lexer: *lex::lexer) (ast::expr | error) = { 378 const tok = match (peek(lexer, ltok::ALIGN, ltok::ALLOC, ltok::APPEND, 379 ltok::FREE, ltok::DELETE, ltok::ABORT, ltok::ASSERT, 380 ltok::INSERT, ltok::STATIC, ltok::SIZE, ltok::LEN, ltok::OFFSET, 381 ltok::VASTART, ltok::VAARG, ltok::VAEND)?) { 382 case let tok: lex::token => 383 yield tok; 384 case void => 385 return plain_expression(lexer); 386 }; 387 switch (tok.0) { 388 case ltok::ALLOC => 389 return alloc_expr(lexer); 390 case ltok::APPEND, ltok::INSERT => 391 return append_insert_expr(lexer, false); 392 case ltok::DELETE => 393 return delete_expr(lexer, false); 394 case ltok::FREE => 395 return free_expr(lexer); 396 case ltok::ABORT, ltok::ASSERT => 397 return assert_expr(lexer, false); 398 case ltok::STATIC => 399 want(lexer, ltok::STATIC)!; 400 return static_expr(lexer); 401 case ltok::ALIGN, ltok::SIZE, ltok::LEN, ltok::OFFSET => 402 return measurement(lexer); 403 case ltok::VASTART => 404 want(lexer, ltok::VASTART)?; 405 want(lexer, ltok::LPAREN)?; 406 want(lexer, ltok::RPAREN)?; 407 return ast::expr { 408 start = tok.2, 409 end = lex::prevloc(lexer), 410 expr = void: ast::vastart_expr: ast::variadic_expr, 411 }; 412 case ltok::VAARG => 413 want(lexer, ltok::VAARG)?; 414 want(lexer, ltok::LPAREN)?; 415 const ap = alloc(objsel(lexer)?)!; 416 want(lexer, ltok::COMMA)?; 417 const _type = alloc(_type(lexer)?)!; 418 want(lexer, ltok::RPAREN)?; 419 return ast::expr { 420 start = tok.2, 421 end = lex::prevloc(lexer), 422 expr = ast::vaarg_expr { 423 ap = ap, 424 _type = _type, 425 }, 426 }; 427 case ltok::VAEND => 428 want(lexer, ltok::VAEND)?; 429 want(lexer, ltok::LPAREN)?; 430 const expr = alloc(objsel(lexer)?)!; 431 want(lexer, ltok::RPAREN)?; 432 return ast::expr { 433 start = tok.2, 434 end = lex::prevloc(lexer), 435 expr = expr: ast::vaend_expr: ast::variadic_expr, 436 }; 437 case => abort(); // Invariant 438 }; 439 }; 440 441 fn call(lexer: *lex::lexer, lvalue: ast::expr) (ast::expr | error) = { 442 let args: []*ast::expr = []; 443 let variadic = false; 444 445 for (true) { 446 match (try(lexer, ltok::RPAREN)?) { 447 case lex::token => break; 448 case void => void; 449 }; 450 451 append(args, alloc(expr(lexer)?)!)!; 452 453 match (try(lexer, ltok::ELLIPSIS)?) { 454 case lex::token => 455 variadic = true; 456 want(lexer, ltok::RPAREN)?; 457 break; 458 case void => void; 459 }; 460 461 switch (want(lexer, ltok::COMMA, ltok::RPAREN)?.0) { 462 case ltok::RPAREN => break; 463 case => void; 464 }; 465 }; 466 467 return ast::expr { 468 start = lvalue.start, 469 end = lex::prevloc(lexer), 470 expr = ast::call_expr { 471 lvalue = alloc(lvalue)!, 472 variadic = variadic, 473 args = args, 474 }, 475 }; 476 }; 477 478 fn cast(lexer: *lex::lexer, lvalue: (ast::expr | void)) (ast::expr | error) = { 479 const lvalue = match (lvalue) { 480 case void => 481 yield unarithm(lexer)?; 482 case let e: ast::expr => 483 yield e; 484 }; 485 const tok = match (try(lexer, ltok::COLON, ltok::AS, ltok::IS)?) { 486 case void => 487 return lvalue; 488 case let tok: lex::token => 489 yield tok.0; 490 }; 491 const kind = switch (tok) { 492 case ltok::COLON => 493 yield ast::cast_kind::CAST; 494 case ltok::AS => 495 yield ast::cast_kind::ASSERTION; 496 case ltok::IS => 497 yield ast::cast_kind::TEST; 498 case => abort(); 499 }; 500 let typ = match (try(lexer, ltok::NULL)?) { 501 case let t: lex::token => 502 yield alloc(ast::_type { 503 start = t.2, 504 end = lex::prevloc(lexer), 505 flags = 0, 506 repr = ast::builtin_type::NULL, 507 })!; 508 case void => 509 yield alloc(_type(lexer)?)!; 510 }; 511 return cast(lexer, ast::expr { 512 start = lvalue.start, 513 end = lex::prevloc(lexer), 514 expr = ast::cast_expr { 515 kind = kind, 516 value = alloc(lvalue)!, 517 _type = typ, 518 }, 519 })?; 520 }; 521 522 fn literal(lexer: *lex::lexer) (ast::expr | error) = { 523 const tok = want(lexer)?; 524 const expr: ast::literal_expr = switch (tok.0) { 525 case ltok::LIT_RCONST, ltok::LIT_STR => 526 yield tok.1 as (rune | str); 527 case ltok::LIT_U8, ltok::LIT_U16, ltok::LIT_U32, ltok::LIT_U64, 528 ltok::LIT_UINT, ltok::LIT_SIZE => 529 yield ast::number_literal { 530 suff = tok.0, 531 value = tok.1 as u64, 532 sign = false, 533 }; 534 case ltok::LIT_I8, ltok::LIT_I16, ltok::LIT_I32, ltok::LIT_I64, 535 ltok::LIT_INT => 536 const n = tok.1 as u64; 537 yield ast::number_literal { 538 suff = tok.0, 539 value = n: i64, 540 sign = false, 541 }; 542 case ltok::LIT_ICONST => 543 const n = tok.1 as u64; 544 yield ast::number_literal { 545 suff = tok.0, 546 value = if (n <= types::I64_MAX: u64) n: i64 else n, 547 sign = false, 548 }; 549 case ltok::LIT_F32, ltok::LIT_F64, ltok::LIT_FCONST => 550 yield ast::number_literal { 551 suff = tok.0, 552 value = tok.1 as f64, 553 sign = false, 554 }; 555 case ltok::VOID => 556 yield void; 557 case ltok::NOMEM => 558 yield nomem; 559 case ltok::DONE => 560 yield done; 561 case ltok::TRUE => 562 yield true; 563 case ltok::FALSE => 564 yield false; 565 case ltok::NULL => 566 yield ast::_null; 567 case => 568 return syntaxerr(lex::mkloc(lexer), "Expected literal expression"); 569 }; 570 return ast::expr { 571 start = tok.2, 572 end = lex::prevloc(lexer), 573 expr = expr, 574 }; 575 }; 576 577 fn control(lexer: *lex::lexer) (ast::expr | error) = { 578 let tok = want(lexer, ltok::BREAK, ltok::CONTINUE, ltok::RETURN)?; 579 let label = if (tok.0 == ltok::BREAK || tok.0 == ltok::CONTINUE) { 580 yield match (try(lexer, ltok::COLON)?) { 581 case lex::token => 582 yield want(lexer, ltok::NAME)?.1 as str; 583 case void => 584 yield ""; 585 }; 586 } else ""; 587 const expr = switch (tok.0) { 588 case ltok::BREAK => 589 yield label: ast::break_expr; 590 case ltok::CONTINUE => 591 yield label: ast::continue_expr; 592 case ltok::RETURN => 593 yield match (peek(lexer, ltok::COMMA, ltok::ELSE, ltok::RBRACE, 594 ltok::RBRACKET, ltok::RPAREN, ltok::SEMICOLON, 595 ltok::EOF)?) { 596 case void => 597 yield alloc(expr(lexer)?)!: ast::return_expr; 598 case lex::token => 599 yield null: ast::return_expr; 600 }; 601 case => abort(); // unreachable 602 }; 603 return ast::expr { 604 start = tok.2, 605 end = lex::prevloc(lexer), 606 expr = expr, 607 }; 608 }; 609 610 fn delete_expr(lexer: *lex::lexer, is_static: bool) (ast::expr | error) = { 611 const start = want(lexer, ltok::DELETE)?; 612 want(lexer, ltok::LPAREN)?; 613 const expr = alloc(postfix(lexer, void)?)!; 614 // TODO: Assert that this was an indexing expression 615 want(lexer, ltok::RPAREN)?; 616 return ast::expr { 617 start = start.2, 618 end = lex::prevloc(lexer), 619 expr = ast::delete_expr { 620 object = expr, 621 is_static = is_static, 622 }, 623 }; 624 }; 625 626 fn compound_expr(lexer: *lex::lexer) (ast::expr | error) = { 627 let items: []*ast::expr = []; 628 629 const start = want(lexer, ltok::LBRACE, ltok::COLON)?; 630 const label = switch (start.0) { 631 case ltok::COLON => 632 const tok = want(lexer, ltok::NAME)?; 633 want(lexer, ltok::LBRACE)?; 634 yield tok.1 as str; 635 case => 636 yield ""; 637 }; 638 639 for (true) { 640 append(items, alloc(stmt(lexer)?)!)!; 641 if (try(lexer, ltok::RBRACE)? is lex::token) { 642 break; 643 }; 644 }; 645 646 return ast::expr { 647 start = start.2, 648 end = lex::prevloc(lexer), 649 expr = ast::compound_expr { 650 exprs = items, 651 label = label, 652 }, 653 }; 654 }; 655 656 fn stmt(lexer: *lex::lexer) (ast::expr | error) = { 657 const expr = match (try(lexer, ltok::DEFER, ltok::DEF, 658 ltok::LET, ltok::CONST, ltok::STATIC)?) { 659 case let tok: lex::token => 660 yield switch (tok.0) { 661 case ltok::DEFER => 662 let expr = alloc(expr(lexer)?)!; 663 yield ast::expr { 664 start = tok.2, 665 end = lex::prevloc(lexer), 666 expr = expr: ast::defer_expr, 667 }; 668 case ltok::DEF, ltok::CONST, ltok::LET => 669 lex::unlex(lexer, tok); 670 yield binding(lexer, false)?; 671 case ltok::STATIC => 672 yield match (peek(lexer, ltok::LET, ltok::CONST)?) { 673 case lex::token => 674 yield binding(lexer, true)?; 675 case void => 676 yield static_expr(lexer)?; 677 }; 678 case => abort(); // unreachable 679 }; 680 case void => 681 yield expr(lexer)?; 682 }; 683 684 want(lexer, ltok::SEMICOLON)?; 685 return expr; 686 }; 687 688 fn for_expr(lexer: *lex::lexer) (ast::expr | error) = { 689 const tok = want(lexer, ltok::FOR)?; 690 const label = if (try(lexer, ltok::COLON)? is lex::token) { 691 const tok = want(lexer, ltok::NAME)?; 692 yield tok.1 as str; 693 } else ""; 694 want(lexer, ltok::LPAREN)?; 695 696 let kind = void: (ast::for_kind | void); 697 let predicate_loc = lex::mkloc(lexer); 698 699 const bindings = match (try(lexer, ltok::LET, ltok::CONST)?) { 700 case let tok: lex::token => 701 const binding_kind = switch (tok.0) { 702 case ltok::LET => 703 yield ast::binding_kind::LET; 704 case ltok::CONST => 705 yield ast::binding_kind::CONST; 706 case => abort(); // unreachable 707 }; 708 709 let bindings: []ast::binding = []; 710 711 for (true) { 712 const (tok, value, _) = want(lexer, 713 ltok::NAME, ltok::LPAREN)?; 714 const binding_name = switch (tok) { 715 case ltok::NAME => 716 yield value as str; 717 case ltok::LPAREN => 718 yield binding_unpack(lexer)?; 719 case => abort(); // unreachable 720 }; 721 const btype: nullable *ast::_type = 722 if (try(lexer, ltok::COLON)? is lex::token) { 723 yield alloc(_type(lexer)?)!; 724 } else null; 725 726 const (tok, _, _) = want(lexer, ltok::EQUAL, 727 ltok::DOUBLE_DOT, ltok::BAND, ltok::ARROW)?; 728 729 if (kind is void) { 730 switch (tok) { 731 case ltok::EQUAL => 732 kind = ast::for_kind::ACCUMULATOR; 733 case ltok::DOUBLE_DOT => 734 kind = ast::for_kind::EACH_VALUE; 735 case ltok::BAND => 736 want(lexer, ltok::DOUBLE_DOT)?; 737 kind = ast::for_kind::EACH_POINTER; 738 case ltok::ARROW => 739 kind = ast::for_kind::ITERATOR; 740 case => abort(); // unreachable 741 }; 742 } else if (kind as ast::for_kind != 743 ast::for_kind::ACCUMULATOR 744 || tok != ltok::EQUAL) { 745 return syntaxerr(lex::mkloc(lexer), 746 "Cannot create multiple bindings in non-c-style loop"); 747 }; 748 749 const init_expr = alloc(expr(lexer)?)!; 750 751 append(bindings, ast::binding { 752 name = binding_name, 753 _type = btype, 754 init = init_expr, 755 })!; 756 757 match (try(lexer, ltok::COMMA)?) { 758 case lex::token => 759 void; 760 case void => 761 break; 762 }; 763 }; 764 765 if (kind as ast::for_kind == ast::for_kind::ACCUMULATOR) { 766 want(lexer, ltok::SEMICOLON)?; 767 }; 768 769 yield alloc(ast::expr { 770 start = predicate_loc, 771 end = lex::prevloc(lexer), 772 expr = ast::binding_expr { 773 is_static = false, 774 kind = binding_kind, 775 bindings = bindings, 776 }, 777 })!; 778 case void => 779 kind = ast::for_kind::ACCUMULATOR; 780 yield null; 781 }; 782 783 const cond: nullable *ast::expr = null; 784 const afterthought: nullable *ast::expr = null; 785 786 if (kind as ast::for_kind == ast::for_kind::ACCUMULATOR) { 787 cond = alloc(expr(lexer)?)!; 788 match (try(lexer, ltok::SEMICOLON)) { 789 case lex::token => 790 afterthought = alloc(expr(lexer)?)!; 791 case void => void; 792 }; 793 }; 794 795 want(lexer, ltok::RPAREN)?; 796 797 const body = alloc(expr(lexer)?)!; 798 return ast::expr { 799 start = tok.2, 800 end = lex::prevloc(lexer), 801 expr = ast::for_expr { 802 kind = kind as ast::for_kind, 803 bindings = bindings, 804 cond = cond, 805 afterthought = afterthought, 806 body = body, 807 label = label, 808 }, 809 }; 810 }; 811 812 fn free_expr(lexer: *lex::lexer) (ast::expr | error) = { 813 const start = want(lexer, ltok::FREE)?; 814 want(lexer, ltok::LPAREN)?; 815 const expr = alloc(expr(lexer)?)!; 816 want(lexer, ltok::RPAREN)?; 817 return ast::expr { 818 start = start.2, 819 end = lex::prevloc(lexer), 820 expr = expr: ast::free_expr, 821 }; 822 }; 823 824 fn if_expr(lexer: *lex::lexer) (ast::expr | error) = { 825 const start = want(lexer, ltok::IF)?; 826 want(lexer, ltok::LPAREN)?; 827 const cond = alloc(expr(lexer)?)!; 828 want(lexer, ltok::RPAREN)?; 829 const tbranch = alloc(expr(lexer)?)!; 830 const fbranch: nullable *ast::expr = match (try(lexer, ltok::ELSE)?) { 831 case void => 832 yield null; 833 case lex::token => 834 yield alloc(expr(lexer)?)!; 835 }; 836 return ast::expr { 837 start = start.2, 838 end = lex::prevloc(lexer), 839 expr = ast::if_expr { 840 cond = cond, 841 tbranch = tbranch, 842 fbranch = fbranch, 843 }, 844 }; 845 }; 846 847 fn indexing(lexer: *lex::lexer, lvalue: ast::expr) (ast::expr | error) = { 848 let is_slice = false; 849 let start: nullable *ast::expr = null, end: nullable *ast::expr = null; 850 851 if (try(lexer, ltok::DOUBLE_DOT)? is lex::token) { 852 is_slice = true; 853 } else { 854 start = alloc(expr(lexer)?)!; 855 }; 856 if (!is_slice && try(lexer, ltok::DOUBLE_DOT)? is lex::token) { 857 is_slice = true; 858 }; 859 if (is_slice && peek(lexer, ltok::RBRACKET)? is void) { 860 end = alloc(expr(lexer)?)!; 861 }; 862 863 want(lexer, ltok::RBRACKET)?; 864 return ast::expr { 865 start = lvalue.start, 866 end = lex::prevloc(lexer), 867 expr = if (is_slice) ast::slice_expr { 868 object = alloc(lvalue)!, 869 start = start, 870 end = end, 871 } else ast::access_index { 872 object = alloc(lvalue)!, 873 index = { 874 assert(end == null); 875 yield start as *ast::expr; 876 }, 877 }, 878 }; 879 }; 880 881 fn objsel(lexer: *lex::lexer) (ast::expr | error) = { 882 let expr = postfix(lexer, void)?; 883 synassert(lex::mkloc(lexer), expr.expr is ast::access_expr, 884 "Expected object selector")?; 885 return expr; 886 }; 887 888 fn idxexpr(lexer: *lex::lexer) (ast::expr | error) = { 889 const expr = postfix(lexer, void)?; 890 synassert(lex::mkloc(lexer), expr.expr is ast::access_expr 891 && expr.expr as ast::access_expr is ast::access_index, 892 "Expected indexing expression")?; 893 return expr; 894 }; 895 896 fn plain_expression(lexer: *lex::lexer) (ast::expr | error) = { 897 let tok = peek(lexer)? as lex::token; 898 if (tok.0 >= ltok::LIT_U8 && tok.0 <= ltok::LAST_LITERAL) { 899 return literal(lexer); 900 }; 901 switch (tok.0) { 902 case ltok::TRUE, ltok::FALSE, ltok::NULL, ltok::VOID, ltok::DONE => 903 return literal(lexer); 904 case ltok::LBRACKET => 905 return plain_array(lexer)?; 906 case ltok::STRUCT => 907 let s = plain_struct(lexer, [])?; 908 return ast::expr { 909 start = tok.2, 910 end = lex::prevloc(lexer), 911 expr = s, 912 }; 913 case ltok::LPAREN => 914 want(lexer, ltok::LPAREN)?; 915 let ex = expr(lexer)?; 916 switch (want(lexer, ltok::RPAREN, ltok::COMMA)?.0) { 917 case ltok::RPAREN => 918 return ex; 919 case ltok::COMMA => 920 return plain_tuple(lexer, ex, tok.2)?; 921 case => abort(); 922 }; 923 case ltok::NAME => 924 let id = ident(lexer)?; 925 match (peek(lexer, ltok::LBRACE)?) { 926 case void => 927 return ast::expr { 928 start = tok.2, 929 end = lex::prevloc(lexer), 930 expr = id: ast::access_identifier, 931 }; 932 case lex::token => 933 let s = plain_struct(lexer, id)?; 934 return ast::expr { 935 start = tok.2, 936 end = lex::prevloc(lexer), 937 expr = s, 938 }; 939 }; 940 case => 941 return syntaxerr(lex::mkloc(lexer), 942 "Unexpected {}, was expecting an expression", 943 lex::tokstr(tok)); 944 }; 945 }; 946 947 fn plain_array(lexer: *lex::lexer) (ast::expr | error) = { 948 const start = want(lexer, ltok::LBRACKET)?; 949 950 let values: []*ast::expr = []; 951 let expand = false; 952 for (true) { 953 match (try(lexer, ltok::RBRACKET)?) { 954 case lex::token => break; 955 case void => void; 956 }; 957 958 append(values, alloc(expr(lexer)?)!)!; 959 960 match (try(lexer, ltok::COMMA, ltok::ELLIPSIS)?) { 961 case void => 962 want(lexer, ltok::RBRACKET)?; 963 break; 964 case let tok: lex::token => 965 switch (tok.0) { 966 case ltok::ELLIPSIS => 967 expand = true; 968 want(lexer, ltok::RBRACKET)?; 969 break; 970 case ltok::COMMA => void; 971 case => abort(); 972 }; 973 }; 974 }; 975 return ast::expr { 976 start = start.2, 977 end = lex::prevloc(lexer), 978 expr = ast::array_literal { 979 expand = expand, 980 values = values, 981 }, 982 }; 983 }; 984 985 fn plain_struct( 986 lexer: *lex::lexer, 987 alias: ast::ident, 988 ) (ast::struct_literal | error) = { 989 if (len(alias) == 0) { 990 want(lexer, ltok::STRUCT)?; 991 }; 992 want(lexer, ltok::LBRACE)?; 993 994 let autofill = false; 995 let fields: [](ast::struct_value | *ast::struct_literal) = []; 996 for (true) { 997 const tok = want(lexer, ltok::ELLIPSIS, 998 ltok::NAME, ltok::STRUCT)?; 999 switch (tok.0) { 1000 case ltok::ELLIPSIS => 1001 synassert(lex::mkloc(lexer), len(alias) != 0, 1002 "Cannot use auto-fill with anonymous struct")?; 1003 autofill = true; 1004 want(lexer, ltok::RBRACE)?; 1005 break; 1006 case ltok::NAME, ltok::STRUCT => 1007 lex::unlex(lexer, tok); 1008 append(fields, struct_field(lexer)?)!; 1009 case => abort(); // unreachable 1010 }; 1011 1012 switch (want(lexer, ltok::COMMA, ltok::RBRACE)?.0) { 1013 case ltok::RBRACE => break; 1014 case ltok::COMMA => 1015 if (try(lexer, ltok::RBRACE)? is lex::token) { 1016 break; 1017 }; 1018 case => abort(); // unreachable 1019 }; 1020 }; 1021 1022 return ast::struct_literal { 1023 autofill = autofill, 1024 alias = alias, 1025 fields = fields, 1026 }; 1027 }; 1028 1029 fn struct_field( 1030 lexer: *lex::lexer, 1031 ) (ast::struct_value | *ast::struct_literal | error) = { 1032 const tok = want(lexer, ltok::NAME, ltok::STRUCT)?; 1033 switch (tok.0) { 1034 case ltok::NAME => 1035 const name = strings::dup(tok.1 as str); 1036 const tok = match (try(lexer, ltok::COLON, 1037 ltok::DOUBLE_COLON, ltok::EQUAL)?) { 1038 case let tok: lex::token => 1039 yield tok; 1040 case void => 1041 let id: ast::ident = alloc([name])!; 1042 return alloc(plain_struct(lexer, id)?)!; 1043 }; 1044 1045 switch (tok.0) { 1046 case ltok::COLON => 1047 const _type = alloc(_type(lexer)?)!; 1048 want(lexer, ltok::EQUAL)?; 1049 const init = alloc(expr(lexer)?)!; 1050 return ast::struct_value { 1051 name = name, 1052 _type = _type, 1053 init = init, 1054 }; 1055 case ltok::DOUBLE_COLON => 1056 let id: ast::ident = alloc([name])!; 1057 let rest = ident(lexer)?; 1058 append(id, rest...)!; 1059 return alloc(plain_struct(lexer, id)?)!; 1060 case ltok::EQUAL => 1061 return ast::struct_value { 1062 name = name, 1063 _type = null, 1064 init = alloc(expr(lexer)?)!, 1065 }; 1066 case => abort(); // Invariant 1067 }; 1068 case ltok::STRUCT => 1069 lex::unlex(lexer, tok); 1070 return alloc(plain_struct(lexer, [])?)!; 1071 case => abort(); // Invariant 1072 }; 1073 }; 1074 1075 fn plain_tuple( 1076 lexer: *lex::lexer, 1077 ex: ast::expr, 1078 start: lex::location 1079 ) (ast::expr | error) = { 1080 let values: []*ast::expr = []; 1081 append(values, alloc(ex)!)!; 1082 1083 for (true) { 1084 append(values, alloc(expr(lexer)?)!)!; 1085 1086 match (try(lexer, ltok::COMMA)?) { 1087 case lex::token => 1088 match (try(lexer, ltok::RPAREN)) { 1089 case lex::token => break; 1090 case => void; 1091 }; 1092 case void => 1093 want(lexer, ltok::RPAREN)?; 1094 break; 1095 }; 1096 }; 1097 1098 return ast::expr { 1099 start = start, 1100 end = lex::prevloc(lexer), 1101 expr = values: ast::tuple_literal, 1102 }; 1103 }; 1104 1105 fn postfix(lexer: *lex::lexer, lvalue: (ast::expr | void)) (ast::expr | error) = { 1106 let lvalue = match (lvalue) { 1107 case void => 1108 yield builtin(lexer)?; 1109 case let ex: ast::expr => 1110 yield ex; 1111 }; 1112 1113 let tok = match (try(lexer, ltok::LPAREN, ltok::DOT, 1114 ltok::LBRACKET, ltok::QUESTION, ltok::LNOT)?) { 1115 case void => 1116 return lvalue; 1117 case let tok: lex::token => 1118 yield tok; 1119 }; 1120 1121 let next = switch (tok.0) { 1122 case ltok::LPAREN => 1123 yield call(lexer, lvalue)?; 1124 case ltok::DOT => 1125 yield postfix_dot(lexer, lvalue)?; 1126 case ltok::LBRACKET => 1127 yield indexing(lexer, lvalue)?; 1128 case ltok::QUESTION => 1129 yield ast::expr { 1130 start = lvalue.start, 1131 end = lex::prevloc(lexer), 1132 expr = alloc(lvalue)!: ast::propagate_expr, 1133 }; 1134 case ltok::LNOT => 1135 yield ast::expr { 1136 start = lvalue.start, 1137 end = lex::prevloc(lexer), 1138 expr = alloc(lvalue)!: ast::error_assert_expr, 1139 }; 1140 case => abort(); 1141 }; 1142 1143 return postfix(lexer, next); 1144 }; 1145 1146 fn postfix_dot( 1147 lexer: *lex::lexer, 1148 lvalue: ast::expr, 1149 ) (ast::expr | error) = { 1150 match (try(lexer, ltok::NAME)?) { 1151 case let tok: lex::token => 1152 return ast::expr { 1153 start = lvalue.start, 1154 end = lex::prevloc(lexer), 1155 expr = ast::access_field { 1156 object = alloc(lvalue)!, 1157 field = tok.1 as str, 1158 }, 1159 }; 1160 case void => 1161 let lit = literal(lexer)?; 1162 let val = lit.expr as ast::literal_expr; 1163 synassert(lex::mkloc(lexer), val is ast::number_literal, 1164 "Expected integer literal")?; 1165 let val = val as ast::number_literal; 1166 return ast::expr { 1167 start = lvalue.start, 1168 end = lex::prevloc(lexer), 1169 expr = ast::access_tuple { 1170 object = alloc(lvalue)!, 1171 value = alloc(lit)!, 1172 }, 1173 }; 1174 }; 1175 }; 1176 1177 fn static_expr(lexer: *lex::lexer) (ast::expr | error) = { 1178 const tok = want(lexer, ltok::ABORT, ltok::ASSERT, ltok::APPEND, 1179 ltok::INSERT, ltok::DELETE)?; 1180 lex::unlex(lexer, tok); 1181 1182 switch (tok.0) { 1183 case ltok::ABORT, ltok::ASSERT => 1184 return assert_expr(lexer, true); 1185 case ltok::APPEND, ltok::INSERT => 1186 let expr = append_insert_expr(lexer, true)?; 1187 return postfix(lexer, expr); 1188 case ltok::DELETE => 1189 return delete_expr(lexer, true); 1190 case => abort(); // unreachable 1191 }; 1192 }; 1193 1194 fn switch_expr(lexer: *lex::lexer) (ast::expr | error) = { 1195 const start = want(lexer, ltok::SWITCH)?; 1196 1197 const label = if (try(lexer, ltok::COLON)? is lex::token) { 1198 const tok = want(lexer, ltok::NAME)?; 1199 yield tok.1 as str; 1200 } else ""; 1201 1202 want(lexer, ltok::LPAREN)?; 1203 const value = expr(lexer)?; 1204 want(lexer, ltok::RPAREN)?; 1205 1206 want(lexer, ltok::LBRACE)?; 1207 1208 let cases: []ast::switch_case = []; 1209 for (true) { 1210 want(lexer, ltok::CASE)?; 1211 1212 let opts: []*ast::expr = []; 1213 if (try(lexer, ltok::ARROW)? is void) for (true) { 1214 append(opts, alloc(expr(lexer)?)!)!; 1215 switch (want(lexer, ltok::ARROW, ltok::COMMA)?.0) { 1216 case ltok::ARROW => 1217 break; 1218 case ltok::COMMA => 1219 if (try(lexer, ltok::ARROW)? is lex::token) { 1220 break; 1221 }; 1222 case => abort(); // unreachable 1223 }; 1224 }; 1225 1226 let exprs: []*ast::expr = []; 1227 for (true) { 1228 append(exprs, alloc(stmt(lexer)?)!)!; 1229 match (peek(lexer, ltok::CASE, ltok::RBRACE)?) { 1230 case lex::token => 1231 break; 1232 case void => void; 1233 }; 1234 }; 1235 1236 append(cases, ast::switch_case { 1237 options = opts, 1238 exprs = exprs, 1239 })!; 1240 1241 if (try(lexer, ltok::RBRACE)? is lex::token) { 1242 break; 1243 }; 1244 }; 1245 1246 return ast::expr { 1247 start = start.2, 1248 end = lex::prevloc(lexer), 1249 expr = ast::switch_expr { 1250 value = alloc(value)!, 1251 cases = cases, 1252 label = label, 1253 }, 1254 }; 1255 }; 1256 1257 fn match_case(lexer: *lex::lexer) (ast::match_case | error) = { 1258 want(lexer, ltok::CASE)?; 1259 let tok = lex::lex(lexer)?; 1260 let loc = tok.2; 1261 let name: str = "", typ: nullable *ast::_type = null; 1262 switch (tok.0) { 1263 case ltok::NULL => 1264 typ = alloc(ast::_type { 1265 start = loc, 1266 end = lex::prevloc(lexer), 1267 flags = 0, 1268 repr = ast::builtin_type::NULL, 1269 })!; 1270 case ltok::LET => 1271 name = want(lexer, ltok::NAME)?.1 as str; 1272 want(lexer, ltok::COLON)?; 1273 typ = alloc(_type(lexer)?)!; 1274 case ltok::ARROW => 1275 lex::unlex(lexer, tok); 1276 case => 1277 lex::unlex(lexer, tok); 1278 typ = alloc(_type(lexer)?)!; 1279 }; 1280 want(lexer, ltok::ARROW)?; 1281 let exprs: []*ast::expr = []; 1282 for (true) { 1283 append(exprs, alloc(stmt(lexer)?)!)!; 1284 if (peek(lexer, ltok::CASE, ltok::RBRACE)? is lex::token) { 1285 break; 1286 }; 1287 }; 1288 1289 return ast::match_case { 1290 name = name, 1291 _type = typ, 1292 exprs = exprs, 1293 }; 1294 }; 1295 1296 fn match_expr(lexer: *lex::lexer) (ast::expr | error) = { 1297 const start = want(lexer, ltok::MATCH)?; 1298 const label = if (try(lexer, ltok::COLON)? is lex::token) { 1299 const tok = want(lexer, ltok::NAME)?; 1300 yield tok.1 as str; 1301 } else ""; 1302 want(lexer, ltok::LPAREN)?; 1303 const value = expr(lexer)?; 1304 want(lexer, ltok::RPAREN)?; 1305 want(lexer, ltok::LBRACE)?; 1306 1307 let cases: []ast::match_case = []; 1308 for (true) { 1309 append(cases, match_case(lexer)?)!; 1310 if (try(lexer, ltok::RBRACE)? is lex::token) { 1311 break; 1312 }; 1313 }; 1314 1315 return ast::expr { 1316 start = start.2, 1317 end = lex::prevloc(lexer), 1318 expr = ast::match_expr { 1319 value = alloc(value)!, 1320 cases = cases, 1321 label = label, 1322 }, 1323 }; 1324 }; 1325 1326 fn unarithm(lexer: *lex::lexer) (ast::expr | error) = { 1327 const tok = match (try(lexer, 1328 ltok::MINUS, ltok::BNOT, ltok::LNOT, ltok::TIMES, ltok::BAND, 1329 ltok::SWITCH, ltok::MATCH, ltok::COLON, ltok::LBRACE)?) { 1330 case void => 1331 return postfix(lexer, void); 1332 case let tok: lex::token => 1333 yield switch (tok.0) { 1334 case ltok::SWITCH => 1335 lex::unlex(lexer, tok); 1336 return switch_expr(lexer); 1337 case ltok::MATCH => 1338 lex::unlex(lexer, tok); 1339 return match_expr(lexer); 1340 case ltok::COLON, ltok::LBRACE => 1341 lex::unlex(lexer, tok); 1342 return compound_expr(lexer); 1343 case => 1344 yield tok; 1345 }; 1346 }; 1347 1348 const op = switch (tok.0) { 1349 case ltok::MINUS => 1350 yield ast::unarithm_op::MINUS; 1351 case ltok::BNOT => 1352 yield ast::unarithm_op::BNOT; 1353 case ltok::LNOT => 1354 yield ast::unarithm_op::LNOT; 1355 case ltok::TIMES => 1356 yield ast::unarithm_op::DEREF; 1357 case ltok::BAND => 1358 yield ast::unarithm_op::ADDR; 1359 case => abort(); 1360 }; 1361 1362 const operand = unarithm(lexer)?; 1363 const expr = :blk { 1364 if (op == ast::unarithm_op::MINUS) match (operand.expr) { 1365 case let c: ast::literal_expr => 1366 match (c) { 1367 case let n: ast::number_literal => 1368 let sign = false; 1369 const val = match (n.value) { 1370 case let i: i64 => 1371 sign = i < 0; 1372 yield -i; 1373 case let u: u64 => void; 1374 case let f: f64 => 1375 sign = math::signf64(f) < 0; 1376 yield -f; 1377 }; 1378 1379 if (val is void) yield; 1380 yield :blk, ast::number_literal { 1381 suff = n.suff, 1382 value = val as (i64 | f64), 1383 sign = sign, 1384 }: ast::literal_expr; 1385 case => void; 1386 }; 1387 case => void; 1388 }; 1389 1390 yield ast::unarithm_expr { 1391 op = op, 1392 operand = alloc(operand)!, 1393 }; 1394 }; 1395 return ast::expr { 1396 start = tok.2, 1397 end = lex::prevloc(lexer), 1398 expr = expr, 1399 }; 1400 }; 1401 1402 fn yield_expr(lexer: *lex::lexer) (ast::expr | error) = { 1403 const start = want(lexer, ltok::YIELD)?; 1404 let label = ""; 1405 let value: nullable *ast::expr = null; 1406 match (try(lexer, ltok::COLON, ltok::COMMA, ltok::ELSE, ltok::RBRACE, 1407 ltok::RBRACKET, ltok::RPAREN, ltok::SEMICOLON, ltok::EOF)?) { 1408 case void => 1409 value = alloc(expr(lexer)?)!; 1410 case let t: lex::token => 1411 if (t.0 == ltok::COLON) { 1412 label = want(lexer, ltok::NAME)?.1 as str; 1413 match (try(lexer, ltok::COMMA)?) { 1414 case void => void; 1415 case lex::token => 1416 value = alloc(expr(lexer)?)!; 1417 }; 1418 } else { 1419 lex::unlex(lexer, t); 1420 }; 1421 }; 1422 return ast::expr { 1423 start = start.2, 1424 end = lex::prevloc(lexer), 1425 expr = ast::yield_expr { 1426 label = label, 1427 value = value, 1428 }, 1429 }; 1430 }; 1431 1432 fn binop_for_tok(tok: lex::token) ast::binarithm_op = { 1433 switch (tok.0) { 1434 case ltok::BAND => 1435 return ast::binarithm_op::BAND; 1436 case ltok::BOR => 1437 return ast::binarithm_op::BOR; 1438 case ltok::BXOR => 1439 return ast::binarithm_op::BXOR; 1440 case ltok::DIV => 1441 return ast::binarithm_op::DIV; 1442 case ltok::GT => 1443 return ast::binarithm_op::GT; 1444 case ltok::GTEQ => 1445 return ast::binarithm_op::GTEQ; 1446 case ltok::LAND => 1447 return ast::binarithm_op::LAND; 1448 case ltok::LEQUAL => 1449 return ast::binarithm_op::LEQUAL; 1450 case ltok::LESS => 1451 return ast::binarithm_op::LESS; 1452 case ltok::LESSEQ => 1453 return ast::binarithm_op::LESSEQ; 1454 case ltok::LOR => 1455 return ast::binarithm_op::LOR; 1456 case ltok::LSHIFT => 1457 return ast::binarithm_op::LSHIFT; 1458 case ltok::LXOR => 1459 return ast::binarithm_op::LXOR; 1460 case ltok::MINUS => 1461 return ast::binarithm_op::MINUS; 1462 case ltok::MODULO => 1463 return ast::binarithm_op::MODULO; 1464 case ltok::NEQUAL => 1465 return ast::binarithm_op::NEQUAL; 1466 case ltok::PLUS => 1467 return ast::binarithm_op::PLUS; 1468 case ltok::RSHIFT => 1469 return ast::binarithm_op::RSHIFT; 1470 case ltok::TIMES => 1471 return ast::binarithm_op::TIMES; 1472 case => abort(); 1473 }; 1474 }; 1475 1476 fn precedence(tok: lex::token) int = { 1477 switch (tok.0) { 1478 case ltok::LOR => 1479 return 0; 1480 case ltok::LXOR => 1481 return 1; 1482 case ltok::LAND => 1483 return 2; 1484 case ltok::LEQUAL, ltok::NEQUAL => 1485 return 3; 1486 case ltok::LESS, ltok::LESSEQ, ltok::GT, ltok::GTEQ => 1487 return 4; 1488 case ltok::BOR => 1489 return 5; 1490 case ltok::BXOR => 1491 return 6; 1492 case ltok::BAND => 1493 return 7; 1494 case ltok::LSHIFT, ltok::RSHIFT => 1495 return 8; 1496 case ltok::PLUS, ltok::MINUS => 1497 return 9; 1498 case ltok::TIMES, ltok::DIV, ltok::MODULO => 1499 return 10; 1500 case => 1501 return -1; 1502 }; 1503 };