difftreelog
fix(rowan) statements bind the tighest
in: master
3 files changed
crates/jrsonnet-rowan-parser/src/parser.rsdiffbeforeafterboth1use std::{cell::Cell, fmt, rc::Rc};23use rowan::{GreenNode, TextRange};45use crate::{6 event::Event,7 marker::{CompletedMarker, Marker},8 nodes::{BinaryOperatorKind, Literal, Number, Text, UnaryOperatorKind},9 token_set::SyntaxKindSet,10 AstToken, SyntaxKind,11 SyntaxKind::*,12 SyntaxNode, T, TS,13};1415pub struct Parse {16 pub green_node: GreenNode,17 pub errors: Vec<LocatedSyntaxError>,18}1920pub struct Parser {21 // TODO: remove all trivia before feeding to parser?22 kinds: Vec<SyntaxKind>,23 pub offset: usize,24 pub events: Vec<Event>,25 pub entered: u32,26 pub hints: Vec<(u32, TextRange, String)>,27 pub last_error_token: usize,28 expected_syntax_tracking_state: Rc<Cell<ExpectedSyntax>>,29 steps: Cell<u64>,30}3132#[derive(Clone, Debug)]33pub enum SyntaxError {34 Unexpected {35 expected: ExpectedSyntax,36 found: SyntaxKind,37 },38 Missing {39 expected: ExpectedSyntax,40 },41 Custom {42 error: String,43 },44 Hint {45 error: String,46 },47}48impl fmt::Display for SyntaxError {49 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {50 match self {51 SyntaxError::Unexpected { expected, found } => {52 write!(f, "unexpected {found:?}, expecting {expected}")53 }54 SyntaxError::Missing { expected } => write!(f, "missing {expected}"),55 SyntaxError::Custom { error } | SyntaxError::Hint { error } => write!(f, "{error}"),56 }57 }58}5960#[derive(Debug)]61pub struct LocatedSyntaxError {62 pub error: SyntaxError,63 pub range: TextRange,64}6566impl Parser {67 pub fn new(kinds: Vec<SyntaxKind>) -> Self {68 Self {69 kinds,70 offset: 0,71 events: vec![],72 entered: 0,73 last_error_token: 0,74 hints: vec![],75 expected_syntax_tracking_state: Rc::new(Cell::new(ExpectedSyntax::Unnamed(TS![]))),76 steps: Cell::new(0),77 }78 }79 pub fn clear_outdated_hints(&mut self) {80 let amount = self81 .hints82 .iter()83 .rev()84 .take_while(|h| h.0 > self.entered)85 .count();86 self.hints.truncate(self.hints.len() - amount);87 }88 fn clear_expected_syntaxes(&self) {89 self.expected_syntax_tracking_state90 .set(ExpectedSyntax::Unnamed(TS![]));91 }92 pub fn start(&mut self) -> Marker {93 let start_event_idx = self.events.len();94 self.events.push(Event::Pending);95 self.entered += 1;96 Marker::new(start_event_idx)97 }98 // pub fn start_ranger(&mut self) -> Ranger {99 // let pos = self.offset;100 // Ranger { pos }101 // }102 pub fn parse(mut self) -> Vec<Event> {103 let m = self.start();104 expr(&mut self);105 if !self.at(EOF) {106 let m = self.start();107 while !self.at(EOF) {108 self.bump();109 }110 m.complete_error(&mut self, "unexpected tokens after end");111 }112 m.complete(&mut self, SOURCE_FILE);113114 self.events115 }116117 pub(crate) fn expect(&mut self, kind: SyntaxKind) {118 self.expect_with_recovery_set(kind, TS![]);119 }120121 pub(crate) fn expect_with_recovery_set(122 &mut self,123 kind: SyntaxKind,124 recovery_set: SyntaxKindSet,125 ) {126 if self.at(kind) {127 if kind != EOF {128 self.bump();129 }130 } else {131 self.error_with_recovery_set(recovery_set);132 }133 }134135 // pub(crate) fn expect_with_no_skip(&mut self, kind: SyntaxKind) {136 // if self.at(kind) {137 // self.bump();138 // } else {139 // self.error_with_no_skip();140 // }141 // }142 pub fn error_with_no_skip(&mut self) -> CompletedMarker {143 self.error_with_recovery_set(SyntaxKindSet::ALL)144 }145146 pub fn error_with_recovery_set(&mut self, recovery_set: SyntaxKindSet) -> CompletedMarker {147 let expected = self.expected_syntax_tracking_state.get();148 self.expected_syntax_tracking_state149 .set(ExpectedSyntax::Unnamed(TS![]));150151 if self.at_end() || self.at_ts(recovery_set) {152 let m = self.start();153 return m.complete_missing(self, expected);154 }155156 let current_token = self.current();157158 self.last_error_token = self.offset;159160 let m = self.start();161 self.bump();162 let m = m.complete_unexpected(self, expected, current_token);163 self.clear_expected_syntaxes();164 m165 }166 fn bump_assert(&mut self, kind: SyntaxKind) {167 assert!(self.at(kind), "expected {kind:?}");168 self.bump_remap(self.current());169 }170 fn bump(&mut self) {171 self.bump_remap(self.current());172 }173 fn bump_remap(&mut self, kind: SyntaxKind) {174 assert_ne!(self.offset, self.kinds.len(), "already at end");175 self.events.push(Event::Token { kind });176 self.offset += 1;177 self.clear_expected_syntaxes();178 }179 fn step(&self) {180 use std::fmt::Write;181 let steps = self.steps.get();182 if steps >= 15_000_000 {183 let mut out = "seems like parsing is stuck".to_owned();184 {185 let last = 20;186 write!(out, "\n\nLast {last} events:").unwrap();187 for (i, event) in self188 .events189 .iter()190 .skip(self.events.len().saturating_sub(last))191 .enumerate()192 {193 write!(out, "\n{i}. {event:?}").unwrap();194 }195 }196 {197 let next = 20;198 write!(out, "\n\nNext {next} tokens:").unwrap();199 for (i, tok) in self.kinds.iter().skip(self.offset).take(next).enumerate() {200 write!(out, "\n{i}. {tok:?}").unwrap();201 }202 }203 panic!("{out}")204 }205 self.steps.set(steps + 1);206 }207 fn nth(&self, i: usize) -> SyntaxKind {208 self.step();209 let mut offset = self.offset;210 for _ in 0..i {211 offset += 1;212 }213 self.kinds.get(offset).copied().unwrap_or(EOF)214 }215 fn current(&self) -> SyntaxKind {216 self.nth(0)217 }218 #[must_use]219 pub(crate) fn expected_syntax_name(&self, name: &'static str) -> ExpectedSyntaxGuard {220 self.expected_syntax_tracking_state221 .set(ExpectedSyntax::Named(name));222223 ExpectedSyntaxGuard::new(Rc::clone(&self.expected_syntax_tracking_state))224 }225 pub fn at(&self, kind: SyntaxKind) -> bool {226 self.nth_at(0, kind)227 }228 pub fn nth_at(&self, n: usize, kind: SyntaxKind) -> bool {229 if n == 0 {230 if let ExpectedSyntax::Unnamed(kinds) = self.expected_syntax_tracking_state.get() {231 let kinds = kinds.with(kind);232 self.expected_syntax_tracking_state233 .set(ExpectedSyntax::Unnamed(kinds));234 }235 }236 self.nth(n) == kind237 }238 pub fn at_ts(&self, set: SyntaxKindSet) -> bool {239 if let ExpectedSyntax::Unnamed(kinds) = self.expected_syntax_tracking_state.get() {240 let kinds = kinds.union(set);241 self.expected_syntax_tracking_state242 .set(ExpectedSyntax::Unnamed(kinds));243 }244 set.contains(self.current())245 }246 pub fn at_end(&self) -> bool {247 self.at(EOF)248 }249}250pub struct ExpectedSyntaxGuard {251 expected_syntax_tracking_state: Rc<Cell<ExpectedSyntax>>,252}253254impl ExpectedSyntaxGuard {255 fn new(expected_syntax_tracking_state: Rc<Cell<ExpectedSyntax>>) -> Self {256 Self {257 expected_syntax_tracking_state,258 }259 }260}261262impl Drop for ExpectedSyntaxGuard {263 fn drop(&mut self) {264 self.expected_syntax_tracking_state265 .set(ExpectedSyntax::Unnamed(TS![]));266 }267}268269#[derive(Clone, Debug, Copy)]270pub enum ExpectedSyntax {271 Named(&'static str),272 Unnamed(SyntaxKindSet),273}274impl fmt::Display for ExpectedSyntax {275 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {276 match self {277 Self::Named(name) => write!(f, "{name}"),278 Self::Unnamed(set) => write!(f, "{set}"),279 }280 }281}282283fn expr(p: &mut Parser) -> CompletedMarker {284 let m = p.start();285 while p.at(T![local]) || p.at(T![assert]) {286 let m = p.start();287288 if p.at(T![local]) {289 p.bump();290 loop {291 if p.at(T![;]) {292 p.bump();293 break;294 }295 bind(p);296297 if p.at(T![,]) {298 p.bump();299 continue;300 }301 p.expect(T![;]);302 break;303 }304 m.complete(p, STMT_LOCAL);305 } else {306 assertion(p);307 p.expect(T![;]);308 m.complete(p, STMT_ASSERT);309 }310 }311 match expr_binding_power(p, 0) {312 Ok(m) | Err(m) => m,313 };314 m.complete(p, EXPR)315}316fn expr_binding_power(317 p: &mut Parser,318 minimum_binding_power: u8,319) -> Result<CompletedMarker, CompletedMarker> {320 let mut lhs = lhs(p)?;321322 while let Some(op) = BinaryOperatorKind::cast(p.current())323 .or_else(|| p.at(T!['{']).then_some(BinaryOperatorKind::MetaObjectApply))324 {325 let (left_binding_power, right_binding_power) = op.binding_power();326 if left_binding_power < minimum_binding_power {327 break;328 }329330 let m = lhs.wrap(p, EXPR, false);331332 // Object apply is not a real operator, we dont have something to bump333 if op != BinaryOperatorKind::MetaObjectApply {334 p.bump();335 }336337 let m = m.precede(p);338 let parsed_rhs = expr_binding_power(p, right_binding_power)339 .map(|v| v.precede(p).complete(p, EXPR))340 .is_ok();341 lhs = m.complete(342 p,343 if op == BinaryOperatorKind::MetaObjectApply {344 EXPR_OBJ_EXTEND345 } else {346 EXPR_BINARY347 },348 );349350 if !parsed_rhs {351 break;352 }353 }354 Ok(lhs)355}356357const COMPSPEC: SyntaxKindSet = TS![for if];358fn compspec(p: &mut Parser) -> CompletedMarker {359 assert!(p.at_ts(COMPSPEC));360 if p.at(T![for]) {361 let m = p.start();362 p.bump();363 destruct(p);364 p.expect(T![in]);365 expr(p);366 m.complete(p, FOR_SPEC)367 } else if p.at(T![if]) {368 let m = p.start();369 p.bump();370 expr(p);371 m.complete(p, IF_SPEC)372 } else {373 unreachable!()374 }375}376377fn comma(p: &mut Parser) -> bool {378 comma_with_alternatives(p, TS![])379}380fn comma_with_alternatives(p: &mut Parser, set: SyntaxKindSet) -> bool {381 if p.at(T![,]) {382 p.bump();383 true384 } else if p.at_ts(set) {385 let _ex = p.expected_syntax_name("comma");386 p.expect_with_recovery_set(T![,], TS![]);387 true388 } else {389 false390 }391}392393fn field_name(p: &mut Parser) {394 let _e = p.expected_syntax_name("field name");395 let m = p.start();396 if p.at(T!['[']) {397 p.bump();398 expr(p);399 p.expect(T![']']);400 m.complete(p, FIELD_NAME_DYNAMIC);401 } else if p.at(IDENT) {402 name(p);403 m.complete(p, FIELD_NAME_FIXED);404 } else if Text::can_cast(p.current()) {405 text(p);406 m.complete(p, FIELD_NAME_FIXED);407 } else {408 m.forget(p);409 // Recover with ::, :::410 p.error_with_recovery_set(TS![; : '(']);411 }412}413fn visibility(p: &mut Parser) {414 let m = p.start();415 if !p.at_ts(TS![:]) {416 p.error_with_recovery_set(TS![=]);417 }418 p.bump();419 'colons: {420 if !p.at_ts(TS![:]) {421 break 'colons;422 }423 p.bump();424 if !p.at_ts(TS![:]) {425 break 'colons;426 }427 p.bump();428 }429 m.complete(p, VISIBILITY);430}431fn assertion(p: &mut Parser) {432 let m = p.start();433 p.bump_assert(T![assert]);434 expr(p);435 if p.at(T![:]) {436 p.bump();437 expr(p);438 }439 m.complete(p, ASSERTION);440}441fn object(p: &mut Parser) -> CompletedMarker {442 let m_t = p.start();443 let m = p.start();444 p.bump_assert(T!['{']);445446 let mut elems = 0;447 let mut compspecs = Vec::new();448 let mut asserts = Vec::new();449 loop {450 if p.at(T!['}']) {451 p.bump();452 break;453 }454 if p.at_ts(TS![for]) {455 if elems == 0 {456 let m = p.start();457 m.complete_missing(p, ExpectedSyntax::Named("field definition"));458 }459 while p.at_ts(COMPSPEC) {460 compspecs.push(compspec(p));461 }462 if comma_with_alternatives(p, TS![;]) {463 continue;464 }465 p.expect(R_BRACE);466 break;467 }468 let m = p.start();469 if p.at(T![local]) {470 obj_local(p);471 m.complete(p, MEMBER_BIND_STMT);472 } else if p.at(T![assert]) {473 assertion(p);474 asserts.push(m.complete(p, MEMBER_ASSERT_STMT));475 } else {476 field_name(p);477 if p.at(T![+]) {478 p.bump();479 }480 let params = if p.at(T!['(']) {481 params_desc(p);482 visibility(p);483 expr(p);484 true485 } else {486 visibility(p);487 if p.at(T![function]) {488 p.bump_assert(T![function]);489 params_desc(p);490 expr(p);491 true492 } else {493 expr(p);494 false495 }496 };497 elems += 1;498499 if params {500 m.complete(p, MEMBER_FIELD_METHOD)501 } else {502 m.complete(p, MEMBER_FIELD_NORMAL)503 };504 }505 while p.at_ts(COMPSPEC) {506 compspecs.push(compspec(p));507 }508 if comma_with_alternatives(p, TS![;]) {509 continue;510 }511 p.expect(R_BRACE);512 break;513 }514515 if elems > 1 && !compspecs.is_empty() {516 for errored in compspecs {517 errored.wrap_error(518 p,519 "compspec may only be used if there is only one object element",520 true,521 );522 }523 m.complete(p, OBJ_BODY_MEMBER_LIST);524 } else if !compspecs.is_empty() {525 for errored in asserts {526 errored.wrap_error(p, "asserts can't be used in object comprehensions", true);527 }528 m.complete(p, OBJ_BODY_COMP);529 } else {530 m.complete(p, OBJ_BODY_MEMBER_LIST);531 }532 m_t.complete(p, EXPR_OBJECT)533}534fn param(p: &mut Parser) {535 let m = p.start();536 destruct(p);537 if p.at(T![=]) {538 p.bump();539 expr(p);540 }541 m.complete(p, PARAM);542}543fn params_desc(p: &mut Parser) -> CompletedMarker {544 let m = p.start();545 p.bump_assert(T!['(']);546547 loop {548 if p.at(T![')']) {549 p.bump();550 break;551 }552 param(p);553 if comma(p) {554 continue;555 }556 p.expect(T![')']);557 break;558 }559560 m.complete(p, PARAMS_DESC)561}562fn args_desc(p: &mut Parser) {563 let m = p.start();564 p.bump_assert(T!['(']);565566 let started_named = Cell::new(false);567 let mut unnamed_after_named = Vec::new();568569 loop {570 if p.at(T![')']) {571 break;572 }573574 let m = p.start();575 if p.at(IDENT) && p.nth_at(1, T![=]) {576 name(p);577 p.bump();578 expr(p);579 m.complete(p, ARG);580 started_named.set(true);581 } else {582 expr(p);583 let arg = m.complete(p, ARG);584 if started_named.get() {585 unnamed_after_named.push(arg);586 }587 }588 if comma(p) {589 continue;590 }591 break;592 }593 p.expect(T![')']);594 if p.at(T![tailstrict]) {595 p.bump();596 }597598 for errored in unnamed_after_named {599 errored.wrap_error(p, "can't use positional arguments after named", true);600 }601602 m.complete(p, ARGS_DESC);603}604605fn array(p: &mut Parser) -> CompletedMarker {606 // Start the list node607 let m = p.start();608 p.bump_assert(T!['[']);609610 let mut compspecs = Vec::new();611 let mut elems = 0;612613 loop {614 if p.at(T![']']) {615 p.bump();616 break;617 }618 if elems != 0 && p.at_ts(TS![for]) {619 while p.at_ts(COMPSPEC) {620 compspecs.push(compspec(p));621 }622 if comma(p) {623 continue;624 }625 p.expect(T![']']);626 break;627 }628 expr(p);629 elems += 1;630 while p.at_ts(COMPSPEC) {631 compspecs.push(compspec(p));632 }633 if comma(p) {634 continue;635 }636 p.expect(T![']']);637 break;638 }639640 if elems > 1 && !compspecs.is_empty() {641 for spec in compspecs {642 spec.wrap_error(643 p,644 "compspec may only be used if there is only one array element",645 true,646 );647 }648649 m.complete(p, EXPR_ARRAY)650 } else if !compspecs.is_empty() {651 m.complete(p, EXPR_ARRAY_COMP)652 } else {653 m.complete(p, EXPR_ARRAY)654 }655}656/// Returns true if it was slice, false if just index657#[must_use]658fn slice_desc_or_index(p: &mut Parser) -> bool {659 let m = p.start();660 p.bump();661 // Start662 if !p.at(T![:]) {663 expr(p);664 }665 if p.at(T![:]) {666 p.bump();667 // End668 if !p.at_ts(TS![']' :]) {669 expr(p).wrap(p, SLICE_DESC_END, true);670 }671 if p.at(T![:]) {672 p.bump();673 // Step674 if !p.at(T![']']) {675 expr(p).wrap(p, SLICE_DESC_STEP, true);676 }677 }678 } else {679 // It was not a slice680 p.expect(T![']']);681 m.forget(p);682 return false;683 }684 p.expect(T![']']);685 m.complete(p, SLICE_DESC);686 true687}688689fn suffix(p: &mut Parser) {690 loop {691 let start = p.start();692 let _marker: CompletedMarker = if p.at(T![?]) {693 p.bump();694 p.expect(T![.]);695 if p.at(IDENT) {696 name(p);697 start.complete(p, SUFFIX_INDEX)698 } else if p.at(T!['[']) {699 p.bump();700 expr(p);701 p.expect(T![']']);702 start.complete(p, SUFFIX_INDEX_EXPR)703 } else {704 start.complete_missing(p, ExpectedSyntax::Named("index"))705 }706 } else if p.at(T![.]) {707 p.bump();708 name(p);709 start.complete(p, SUFFIX_INDEX)710 } else if p.at(T!['[']) {711 if slice_desc_or_index(p) {712 start.complete(p, SUFFIX_SLICE)713 } else {714 start.complete(p, SUFFIX_INDEX_EXPR)715 }716 } else if p.at(T!['(']) {717 args_desc(p);718 start.complete(p, SUFFIX_APPLY)719 } else {720 start.forget(p);721 break;722 };723 }724}725726fn lhs(p: &mut Parser) -> Result<CompletedMarker, CompletedMarker> {727 let lhs = lhs_basic(p)?;728729 suffix(p);730731 Ok(lhs)732}733fn name(p: &mut Parser) {734 let m = p.start();735 p.expect(IDENT);736 m.complete(p, NAME);737}738fn destruct_rest(p: &mut Parser) {739 let m = p.start();740 p.bump_assert(T![...]);741 if p.at(IDENT) {742 p.bump();743 }744 m.complete(p, DESTRUCT_REST);745}746fn destruct_object_field(p: &mut Parser) {747 let m = p.start();748 name(p);749 if p.at(T![:]) {750 p.bump();751 destruct(p);752 }753 if p.at(T![=]) {754 p.bump();755 expr(p);756 }757 m.complete(p, DESTRUCT_OBJECT_FIELD);758}759fn obj_local(p: &mut Parser) {760 let m = p.start();761 p.bump_assert(T![local]);762 bind(p);763 m.complete(p, OBJ_LOCAL);764}765fn destruct(p: &mut Parser) -> CompletedMarker {766 let m = p.start();767 let _ex = p.expected_syntax_name("destruction specifier");768 if p.at(T![?]) {769 p.bump();770 m.complete(p, DESTRUCT_SKIP)771 } else if p.at(T!['[']) {772 p.bump();773 // let mut had_rest = false;774 loop {775 if p.at(T![']']) {776 p.bump();777 break;778 } else if p.at(T![...]) {779 // let m_err = p.start_ranger();780 destruct_rest(p);781 // if had_rest {782 // p.custom_error(m_err.finish(p), "only one rest can be present in array");783 // }784 // had_rest = true;785 } else {786 destruct(p);787 }788 if p.at(T![,]) {789 p.bump();790 continue;791 }792 p.expect(T![']']);793 break;794 }795 m.complete(p, DESTRUCT_ARRAY)796 } else if p.at(T!['{']) {797 p.bump();798 let mut had_rest = false;799 loop {800 if p.at(T!['}']) {801 p.bump();802 break;803 } else if p.at(T![...]) {804 // let m_err = p.start_ranger();805 destruct_rest(p);806 // if had_rest {807 // p.custom_error(m_err.finish(p), "only one rest can be present in object");808 // }809 had_rest = true;810 } else {811 if had_rest {812 p.error_with_recovery_set(TS![]);813 }814 destruct_object_field(p);815 }816 if p.at(T![,]) {817 p.bump();818 continue;819 }820 p.expect(T!['}']);821 break;822 }823 m.complete(p, DESTRUCT_OBJECT)824 } else if p.at(IDENT) {825 name(p);826 m.complete(p, DESTRUCT_FULL)827 } else {828 m.forget(p);829 p.error_with_recovery_set(TS![; , '}', '(', :])830 }831}832fn bind(p: &mut Parser) {833 let m = p.start();834 if p.at(IDENT) && p.nth_at(1, T!['(']) {835 name(p);836 params_desc(p);837 p.expect(T![=]);838 expr(p);839 m.complete(p, BIND_FUNCTION)840 } else if p.at(IDENT) && p.nth_at(1, T![=]) && p.nth_at(2, T![function]) {841 name(p);842 p.expect(T![=]);843 p.expect(T![function]);844 params_desc(p);845 expr(p);846 m.complete(p, BIND_FUNCTION)847 } else {848 destruct(p);849 p.expect(T![=]);850 expr(p);851 m.complete(p, BIND_DESTRUCT)852 };853}854fn text(p: &mut Parser) {855 assert!(Text::can_cast(p.current()));856 p.bump();857}858fn number(p: &mut Parser) {859 assert!(Number::can_cast(p.current()));860 p.bump();861}862fn literal(p: &mut Parser) {863 assert!(Literal::can_cast(p.current()));864 p.bump();865}866fn lhs_basic(p: &mut Parser) -> Result<CompletedMarker, CompletedMarker> {867 let _e = p.expected_syntax_name("expression");868 Ok(if Literal::can_cast(p.current()) {869 let m = p.start();870 literal(p);871 m.complete(p, EXPR_LITERAL)872 } else if Text::can_cast(p.current()) {873 let m = p.start();874 text(p);875 m.complete(p, EXPR_STRING)876 } else if Number::can_cast(p.current()) {877 let m = p.start();878 number(p);879 m.complete(p, EXPR_NUMBER)880 } else if p.at(IDENT) {881 let m = p.start();882 name(p);883 m.complete(p, EXPR_VAR)884 } else if p.at(T![if]) {885 let m = p.start();886 p.bump();887 expr(p);888 p.expect(T![then]);889 expr(p).wrap(p, TRUE_EXPR, true);890 if p.at(T![else]) {891 p.bump();892 expr(p).wrap(p, FALSE_EXPR, true);893 }894 m.complete(p, EXPR_IF_THEN_ELSE)895 } else if p.at(T!['[']) {896 array(p)897 } else if p.at(T!['{']) {898 object(p)899 } else if p.at(T![function]) {900 let m = p.start();901 p.bump();902 params_desc(p);903 expr(p);904 m.complete(p, EXPR_FUNCTION)905 } else if p.at(T![error]) {906 let m = p.start();907 p.bump();908 expr(p);909 m.complete(p, EXPR_ERROR)910 } else if p.at(T![import]) || p.at(T![importstr]) || p.at(T![importbin]) {911 let m = p.start();912 p.bump();913 text(p);914 m.complete(p, EXPR_IMPORT)915 } else if let Some(op) = UnaryOperatorKind::cast(p.current()) {916 let ((), right_binding_power) = op.binding_power();917918 let m = p.start();919 p.bump();920 let _ = expr_binding_power(p, right_binding_power)921 .map(|v| v.precede(p).complete(p, EXPR));922 m.complete(p, EXPR_UNARY)923 } else if p.at(T!['(']) {924 let m = p.start();925 p.bump();926 expr(p);927 p.expect(T![')']);928 m.complete(p, EXPR_PARENED)929 } else {930 return Err(p.error_with_no_skip());931 })932}933934impl Parse {935 pub fn syntax(&self) -> SyntaxNode {936 SyntaxNode::new_root(self.green_node.clone())937 }938}1use std::{cell::Cell, fmt, rc::Rc};23use rowan::{GreenNode, TextRange};45use crate::{6 event::Event,7 marker::{CompletedMarker, Marker},8 nodes::{BinaryOperatorKind, Literal, Number, Text, UnaryOperatorKind},9 token_set::SyntaxKindSet,10 AstToken, SyntaxKind,11 SyntaxKind::*,12 SyntaxNode, T, TS,13};1415pub struct Parse {16 pub green_node: GreenNode,17 pub errors: Vec<LocatedSyntaxError>,18}1920pub struct Parser {21 // TODO: remove all trivia before feeding to parser?22 kinds: Vec<SyntaxKind>,23 pub offset: usize,24 pub events: Vec<Event>,25 pub entered: u32,26 pub hints: Vec<(u32, TextRange, String)>,27 pub last_error_token: usize,28 expected_syntax_tracking_state: Rc<Cell<ExpectedSyntax>>,29 steps: Cell<u64>,30}3132#[derive(Clone, Debug)]33pub enum SyntaxError {34 Unexpected {35 expected: ExpectedSyntax,36 found: SyntaxKind,37 },38 Missing {39 expected: ExpectedSyntax,40 },41 Custom {42 error: String,43 },44 Hint {45 error: String,46 },47}48impl fmt::Display for SyntaxError {49 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {50 match self {51 SyntaxError::Unexpected { expected, found } => {52 write!(f, "unexpected {found:?}, expecting {expected}")53 }54 SyntaxError::Missing { expected } => write!(f, "missing {expected}"),55 SyntaxError::Custom { error } | SyntaxError::Hint { error } => write!(f, "{error}"),56 }57 }58}5960#[derive(Debug)]61pub struct LocatedSyntaxError {62 pub error: SyntaxError,63 pub range: TextRange,64}6566impl Parser {67 pub fn new(kinds: Vec<SyntaxKind>) -> Self {68 Self {69 kinds,70 offset: 0,71 events: vec![],72 entered: 0,73 last_error_token: 0,74 hints: vec![],75 expected_syntax_tracking_state: Rc::new(Cell::new(ExpectedSyntax::Unnamed(TS![]))),76 steps: Cell::new(0),77 }78 }79 pub fn clear_outdated_hints(&mut self) {80 let amount = self81 .hints82 .iter()83 .rev()84 .take_while(|h| h.0 > self.entered)85 .count();86 self.hints.truncate(self.hints.len() - amount);87 }88 fn clear_expected_syntaxes(&self) {89 self.expected_syntax_tracking_state90 .set(ExpectedSyntax::Unnamed(TS![]));91 }92 pub fn start(&mut self) -> Marker {93 let start_event_idx = self.events.len();94 self.events.push(Event::Pending);95 self.entered += 1;96 Marker::new(start_event_idx)97 }98 // pub fn start_ranger(&mut self) -> Ranger {99 // let pos = self.offset;100 // Ranger { pos }101 // }102 pub fn parse(mut self) -> Vec<Event> {103 let m = self.start();104 expr(&mut self);105 if !self.at(EOF) {106 let m = self.start();107 while !self.at(EOF) {108 self.bump();109 }110 m.complete_error(&mut self, "unexpected tokens after end");111 }112 m.complete(&mut self, SOURCE_FILE);113114 self.events115 }116117 pub(crate) fn expect(&mut self, kind: SyntaxKind) {118 self.expect_with_recovery_set(kind, TS![]);119 }120121 pub(crate) fn expect_with_recovery_set(122 &mut self,123 kind: SyntaxKind,124 recovery_set: SyntaxKindSet,125 ) {126 if self.at(kind) {127 if kind != EOF {128 self.bump();129 }130 } else {131 self.error_with_recovery_set(recovery_set);132 }133 }134135 // pub(crate) fn expect_with_no_skip(&mut self, kind: SyntaxKind) {136 // if self.at(kind) {137 // self.bump();138 // } else {139 // self.error_with_no_skip();140 // }141 // }142 pub fn error_with_no_skip(&mut self) -> CompletedMarker {143 self.error_with_recovery_set(SyntaxKindSet::ALL)144 }145146 pub fn error_with_recovery_set(&mut self, recovery_set: SyntaxKindSet) -> CompletedMarker {147 let expected = self.expected_syntax_tracking_state.get();148 self.expected_syntax_tracking_state149 .set(ExpectedSyntax::Unnamed(TS![]));150151 if self.at_end() || self.at_ts(recovery_set) {152 let m = self.start();153 return m.complete_missing(self, expected);154 }155156 let current_token = self.current();157158 self.last_error_token = self.offset;159160 let m = self.start();161 self.bump();162 let m = m.complete_unexpected(self, expected, current_token);163 self.clear_expected_syntaxes();164 m165 }166 fn bump_assert(&mut self, kind: SyntaxKind) {167 assert!(self.at(kind), "expected {kind:?}");168 self.bump_remap(self.current());169 }170 fn bump(&mut self) {171 self.bump_remap(self.current());172 }173 fn bump_remap(&mut self, kind: SyntaxKind) {174 assert_ne!(self.offset, self.kinds.len(), "already at end");175 self.events.push(Event::Token { kind });176 self.offset += 1;177 self.clear_expected_syntaxes();178 }179 fn step(&self) {180 use std::fmt::Write;181 let steps = self.steps.get();182 if steps >= 15_000_000 {183 let mut out = "seems like parsing is stuck".to_owned();184 {185 let last = 20;186 write!(out, "\n\nLast {last} events:").unwrap();187 for (i, event) in self188 .events189 .iter()190 .skip(self.events.len().saturating_sub(last))191 .enumerate()192 {193 write!(out, "\n{i}. {event:?}").unwrap();194 }195 }196 {197 let next = 20;198 write!(out, "\n\nNext {next} tokens:").unwrap();199 for (i, tok) in self.kinds.iter().skip(self.offset).take(next).enumerate() {200 write!(out, "\n{i}. {tok:?}").unwrap();201 }202 }203 panic!("{out}")204 }205 self.steps.set(steps + 1);206 }207 fn nth(&self, i: usize) -> SyntaxKind {208 self.step();209 let mut offset = self.offset;210 for _ in 0..i {211 offset += 1;212 }213 self.kinds.get(offset).copied().unwrap_or(EOF)214 }215 fn current(&self) -> SyntaxKind {216 self.nth(0)217 }218 #[must_use]219 pub(crate) fn expected_syntax_name(&self, name: &'static str) -> ExpectedSyntaxGuard {220 self.expected_syntax_tracking_state221 .set(ExpectedSyntax::Named(name));222223 ExpectedSyntaxGuard::new(Rc::clone(&self.expected_syntax_tracking_state))224 }225 pub fn at(&self, kind: SyntaxKind) -> bool {226 self.nth_at(0, kind)227 }228 pub fn nth_at(&self, n: usize, kind: SyntaxKind) -> bool {229 if n == 0 {230 if let ExpectedSyntax::Unnamed(kinds) = self.expected_syntax_tracking_state.get() {231 let kinds = kinds.with(kind);232 self.expected_syntax_tracking_state233 .set(ExpectedSyntax::Unnamed(kinds));234 }235 }236 self.nth(n) == kind237 }238 pub fn at_ts(&self, set: SyntaxKindSet) -> bool {239 if let ExpectedSyntax::Unnamed(kinds) = self.expected_syntax_tracking_state.get() {240 let kinds = kinds.union(set);241 self.expected_syntax_tracking_state242 .set(ExpectedSyntax::Unnamed(kinds));243 }244 set.contains(self.current())245 }246 pub fn at_end(&self) -> bool {247 self.at(EOF)248 }249}250pub struct ExpectedSyntaxGuard {251 expected_syntax_tracking_state: Rc<Cell<ExpectedSyntax>>,252}253254impl ExpectedSyntaxGuard {255 fn new(expected_syntax_tracking_state: Rc<Cell<ExpectedSyntax>>) -> Self {256 Self {257 expected_syntax_tracking_state,258 }259 }260}261262impl Drop for ExpectedSyntaxGuard {263 fn drop(&mut self) {264 self.expected_syntax_tracking_state265 .set(ExpectedSyntax::Unnamed(TS![]));266 }267}268269#[derive(Clone, Debug, Copy)]270pub enum ExpectedSyntax {271 Named(&'static str),272 Unnamed(SyntaxKindSet),273}274impl fmt::Display for ExpectedSyntax {275 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {276 match self {277 Self::Named(name) => write!(f, "{name}"),278 Self::Unnamed(set) => write!(f, "{set}"),279 }280 }281}282283fn expr(p: &mut Parser) -> CompletedMarker {284 let m = p.start();285 while p.at(T![local]) || p.at(T![assert]) {286 let m = p.start();287288 if p.at(T![local]) {289 p.bump();290 loop {291 if p.at(T![;]) {292 p.bump();293 break;294 }295 bind(p);296297 if p.at(T![,]) {298 p.bump();299 continue;300 }301 p.expect(T![;]);302 break;303 }304 m.complete(p, STMT_LOCAL);305 } else {306 assertion(p);307 p.expect(T![;]);308 m.complete(p, STMT_ASSERT);309 }310 }311 match expr_binding_power(p, 0) {312 Ok(m) | Err(m) => m,313 };314 m.complete(p, EXPR)315}316317fn expr_binding_power(318 p: &mut Parser,319 minimum_binding_power: u8,320) -> Result<CompletedMarker, CompletedMarker> {321 let mut lhs = lhs(p)?;322323 while let Some(op) = BinaryOperatorKind::cast(p.current())324 .or_else(|| p.at(T!['{']).then_some(BinaryOperatorKind::MetaObjectApply))325 {326 let (left_binding_power, right_binding_power) = op.binding_power();327 if left_binding_power < minimum_binding_power {328 break;329 }330331 let m = lhs.wrap(p, EXPR, false);332333 // Object apply is not a real operator, we dont have something to bump334 if op != BinaryOperatorKind::MetaObjectApply {335 p.bump();336 }337338 let m = m.precede(p);339 let parsed_rhs = if p.at(T![local]) || p.at(T![assert]) {340 expr(p);341 true342 } else {343 expr_binding_power(p, right_binding_power)344 .map(|v| v.precede(p).complete(p, EXPR))345 .is_ok()346 };347 lhs = m.complete(348 p,349 if op == BinaryOperatorKind::MetaObjectApply {350 EXPR_OBJ_EXTEND351 } else {352 EXPR_BINARY353 },354 );355356 if !parsed_rhs {357 break;358 }359 }360 Ok(lhs)361}362363const COMPSPEC: SyntaxKindSet = TS![for if];364fn compspec(p: &mut Parser) -> CompletedMarker {365 assert!(p.at_ts(COMPSPEC));366 if p.at(T![for]) {367 let m = p.start();368 p.bump();369 destruct(p);370 p.expect(T![in]);371 expr(p);372 m.complete(p, FOR_SPEC)373 } else if p.at(T![if]) {374 let m = p.start();375 p.bump();376 expr(p);377 m.complete(p, IF_SPEC)378 } else {379 unreachable!()380 }381}382383fn comma(p: &mut Parser) -> bool {384 comma_with_alternatives(p, TS![])385}386fn comma_with_alternatives(p: &mut Parser, set: SyntaxKindSet) -> bool {387 if p.at(T![,]) {388 p.bump();389 true390 } else if p.at_ts(set) {391 let _ex = p.expected_syntax_name("comma");392 p.expect_with_recovery_set(T![,], TS![]);393 true394 } else {395 false396 }397}398399fn field_name(p: &mut Parser) {400 let _e = p.expected_syntax_name("field name");401 let m = p.start();402 if p.at(T!['[']) {403 p.bump();404 expr(p);405 p.expect(T![']']);406 m.complete(p, FIELD_NAME_DYNAMIC);407 } else if p.at(IDENT) {408 name(p);409 m.complete(p, FIELD_NAME_FIXED);410 } else if Text::can_cast(p.current()) {411 text(p);412 m.complete(p, FIELD_NAME_FIXED);413 } else {414 m.forget(p);415 // Recover with ::, :::416 p.error_with_recovery_set(TS![; : '(']);417 }418}419fn visibility(p: &mut Parser) {420 let m = p.start();421 if !p.at_ts(TS![:]) {422 p.error_with_recovery_set(TS![=]);423 }424 p.bump();425 'colons: {426 if !p.at_ts(TS![:]) {427 break 'colons;428 }429 p.bump();430 if !p.at_ts(TS![:]) {431 break 'colons;432 }433 p.bump();434 }435 m.complete(p, VISIBILITY);436}437fn assertion(p: &mut Parser) {438 let m = p.start();439 p.bump_assert(T![assert]);440 expr(p);441 if p.at(T![:]) {442 p.bump();443 expr(p);444 }445 m.complete(p, ASSERTION);446}447fn object(p: &mut Parser) -> CompletedMarker {448 let m_t = p.start();449 let m = p.start();450 p.bump_assert(T!['{']);451452 let mut elems = 0;453 let mut compspecs = Vec::new();454 let mut asserts = Vec::new();455 loop {456 if p.at(T!['}']) {457 p.bump();458 break;459 }460 if p.at_ts(TS![for]) {461 if elems == 0 {462 let m = p.start();463 m.complete_missing(p, ExpectedSyntax::Named("field definition"));464 }465 while p.at_ts(COMPSPEC) {466 compspecs.push(compspec(p));467 }468 if comma_with_alternatives(p, TS![;]) {469 continue;470 }471 p.expect(R_BRACE);472 break;473 }474 let m = p.start();475 if p.at(T![local]) {476 obj_local(p);477 m.complete(p, MEMBER_BIND_STMT);478 } else if p.at(T![assert]) {479 assertion(p);480 asserts.push(m.complete(p, MEMBER_ASSERT_STMT));481 } else {482 field_name(p);483 if p.at(T![+]) {484 p.bump();485 }486 let params = if p.at(T!['(']) {487 params_desc(p);488 visibility(p);489 expr(p);490 true491 } else {492 visibility(p);493 if p.at(T![function]) {494 p.bump_assert(T![function]);495 params_desc(p);496 expr(p);497 true498 } else {499 expr(p);500 false501 }502 };503 elems += 1;504505 if params {506 m.complete(p, MEMBER_FIELD_METHOD)507 } else {508 m.complete(p, MEMBER_FIELD_NORMAL)509 };510 }511 while p.at_ts(COMPSPEC) {512 compspecs.push(compspec(p));513 }514 if comma_with_alternatives(p, TS![;]) {515 continue;516 }517 p.expect(R_BRACE);518 break;519 }520521 if elems > 1 && !compspecs.is_empty() {522 for errored in compspecs {523 errored.wrap_error(524 p,525 "compspec may only be used if there is only one object element",526 true,527 );528 }529 m.complete(p, OBJ_BODY_MEMBER_LIST);530 } else if !compspecs.is_empty() {531 for errored in asserts {532 errored.wrap_error(p, "asserts can't be used in object comprehensions", true);533 }534 m.complete(p, OBJ_BODY_COMP);535 } else {536 m.complete(p, OBJ_BODY_MEMBER_LIST);537 }538 m_t.complete(p, EXPR_OBJECT)539}540fn param(p: &mut Parser) {541 let m = p.start();542 destruct(p);543 if p.at(T![=]) {544 p.bump();545 expr(p);546 }547 m.complete(p, PARAM);548}549fn params_desc(p: &mut Parser) -> CompletedMarker {550 let m = p.start();551 p.bump_assert(T!['(']);552553 loop {554 if p.at(T![')']) {555 p.bump();556 break;557 }558 param(p);559 if comma(p) {560 continue;561 }562 p.expect(T![')']);563 break;564 }565566 m.complete(p, PARAMS_DESC)567}568fn args_desc(p: &mut Parser) {569 let m = p.start();570 p.bump_assert(T!['(']);571572 let started_named = Cell::new(false);573 let mut unnamed_after_named = Vec::new();574575 loop {576 if p.at(T![')']) {577 break;578 }579580 let m = p.start();581 if p.at(IDENT) && p.nth_at(1, T![=]) {582 name(p);583 p.bump();584 expr(p);585 m.complete(p, ARG);586 started_named.set(true);587 } else {588 expr(p);589 let arg = m.complete(p, ARG);590 if started_named.get() {591 unnamed_after_named.push(arg);592 }593 }594 if comma(p) {595 continue;596 }597 break;598 }599 p.expect(T![')']);600 if p.at(T![tailstrict]) {601 p.bump();602 }603604 for errored in unnamed_after_named {605 errored.wrap_error(p, "can't use positional arguments after named", true);606 }607608 m.complete(p, ARGS_DESC);609}610611fn array(p: &mut Parser) -> CompletedMarker {612 // Start the list node613 let m = p.start();614 p.bump_assert(T!['[']);615616 let mut compspecs = Vec::new();617 let mut elems = 0;618619 loop {620 if p.at(T![']']) {621 p.bump();622 break;623 }624 if elems != 0 && p.at_ts(TS![for]) {625 while p.at_ts(COMPSPEC) {626 compspecs.push(compspec(p));627 }628 if comma(p) {629 continue;630 }631 p.expect(T![']']);632 break;633 }634 expr(p);635 elems += 1;636 while p.at_ts(COMPSPEC) {637 compspecs.push(compspec(p));638 }639 if comma(p) {640 continue;641 }642 p.expect(T![']']);643 break;644 }645646 if elems > 1 && !compspecs.is_empty() {647 for spec in compspecs {648 spec.wrap_error(649 p,650 "compspec may only be used if there is only one array element",651 true,652 );653 }654655 m.complete(p, EXPR_ARRAY)656 } else if !compspecs.is_empty() {657 m.complete(p, EXPR_ARRAY_COMP)658 } else {659 m.complete(p, EXPR_ARRAY)660 }661}662/// Returns true if it was slice, false if just index663#[must_use]664fn slice_desc_or_index(p: &mut Parser) -> bool {665 let m = p.start();666 p.bump();667 // Start668 if !p.at(T![:]) {669 expr(p);670 }671 if p.at(T![:]) {672 p.bump();673 // End674 if !p.at_ts(TS![']' :]) {675 expr(p).wrap(p, SLICE_DESC_END, true);676 }677 if p.at(T![:]) {678 p.bump();679 // Step680 if !p.at(T![']']) {681 expr(p).wrap(p, SLICE_DESC_STEP, true);682 }683 }684 } else {685 // It was not a slice686 p.expect(T![']']);687 m.forget(p);688 return false;689 }690 p.expect(T![']']);691 m.complete(p, SLICE_DESC);692 true693}694695fn suffix(p: &mut Parser) {696 loop {697 let start = p.start();698 let _marker: CompletedMarker = if p.at(T![?]) {699 p.bump();700 p.expect(T![.]);701 if p.at(IDENT) {702 name(p);703 start.complete(p, SUFFIX_INDEX)704 } else if p.at(T!['[']) {705 p.bump();706 expr(p);707 p.expect(T![']']);708 start.complete(p, SUFFIX_INDEX_EXPR)709 } else {710 start.complete_missing(p, ExpectedSyntax::Named("index"))711 }712 } else if p.at(T![.]) {713 p.bump();714 name(p);715 start.complete(p, SUFFIX_INDEX)716 } else if p.at(T!['[']) {717 if slice_desc_or_index(p) {718 start.complete(p, SUFFIX_SLICE)719 } else {720 start.complete(p, SUFFIX_INDEX_EXPR)721 }722 } else if p.at(T!['(']) {723 args_desc(p);724 start.complete(p, SUFFIX_APPLY)725 } else {726 start.forget(p);727 break;728 };729 }730}731732fn lhs(p: &mut Parser) -> Result<CompletedMarker, CompletedMarker> {733 let lhs = lhs_basic(p)?;734735 suffix(p);736737 Ok(lhs)738}739fn name(p: &mut Parser) {740 let m = p.start();741 p.expect(IDENT);742 m.complete(p, NAME);743}744fn destruct_rest(p: &mut Parser) {745 let m = p.start();746 p.bump_assert(T![...]);747 if p.at(IDENT) {748 p.bump();749 }750 m.complete(p, DESTRUCT_REST);751}752fn destruct_object_field(p: &mut Parser) {753 let m = p.start();754 name(p);755 if p.at(T![:]) {756 p.bump();757 destruct(p);758 }759 if p.at(T![=]) {760 p.bump();761 expr(p);762 }763 m.complete(p, DESTRUCT_OBJECT_FIELD);764}765fn obj_local(p: &mut Parser) {766 let m = p.start();767 p.bump_assert(T![local]);768 bind(p);769 m.complete(p, OBJ_LOCAL);770}771fn destruct(p: &mut Parser) -> CompletedMarker {772 let m = p.start();773 let _ex = p.expected_syntax_name("destruction specifier");774 if p.at(T![?]) {775 p.bump();776 m.complete(p, DESTRUCT_SKIP)777 } else if p.at(T!['[']) {778 p.bump();779 // let mut had_rest = false;780 loop {781 if p.at(T![']']) {782 p.bump();783 break;784 } else if p.at(T![...]) {785 // let m_err = p.start_ranger();786 destruct_rest(p);787 // if had_rest {788 // p.custom_error(m_err.finish(p), "only one rest can be present in array");789 // }790 // had_rest = true;791 } else {792 destruct(p);793 }794 if p.at(T![,]) {795 p.bump();796 continue;797 }798 p.expect(T![']']);799 break;800 }801 m.complete(p, DESTRUCT_ARRAY)802 } else if p.at(T!['{']) {803 p.bump();804 let mut had_rest = false;805 loop {806 if p.at(T!['}']) {807 p.bump();808 break;809 } else if p.at(T![...]) {810 // let m_err = p.start_ranger();811 destruct_rest(p);812 // if had_rest {813 // p.custom_error(m_err.finish(p), "only one rest can be present in object");814 // }815 had_rest = true;816 } else {817 if had_rest {818 p.error_with_recovery_set(TS![]);819 }820 destruct_object_field(p);821 }822 if p.at(T![,]) {823 p.bump();824 continue;825 }826 p.expect(T!['}']);827 break;828 }829 m.complete(p, DESTRUCT_OBJECT)830 } else if p.at(IDENT) {831 name(p);832 m.complete(p, DESTRUCT_FULL)833 } else {834 m.forget(p);835 p.error_with_recovery_set(TS![; , '}', '(', :])836 }837}838fn bind(p: &mut Parser) {839 let m = p.start();840 if p.at(IDENT) && p.nth_at(1, T!['(']) {841 name(p);842 params_desc(p);843 p.expect(T![=]);844 expr(p);845 m.complete(p, BIND_FUNCTION)846 } else if p.at(IDENT) && p.nth_at(1, T![=]) && p.nth_at(2, T![function]) {847 name(p);848 p.expect(T![=]);849 p.expect(T![function]);850 params_desc(p);851 expr(p);852 m.complete(p, BIND_FUNCTION)853 } else {854 destruct(p);855 p.expect(T![=]);856 expr(p);857 m.complete(p, BIND_DESTRUCT)858 };859}860fn text(p: &mut Parser) {861 assert!(Text::can_cast(p.current()));862 p.bump();863}864fn number(p: &mut Parser) {865 assert!(Number::can_cast(p.current()));866 p.bump();867}868fn literal(p: &mut Parser) {869 assert!(Literal::can_cast(p.current()));870 p.bump();871}872fn lhs_basic(p: &mut Parser) -> Result<CompletedMarker, CompletedMarker> {873 let _e = p.expected_syntax_name("expression");874 Ok(if Literal::can_cast(p.current()) {875 let m = p.start();876 literal(p);877 m.complete(p, EXPR_LITERAL)878 } else if Text::can_cast(p.current()) {879 let m = p.start();880 text(p);881 m.complete(p, EXPR_STRING)882 } else if Number::can_cast(p.current()) {883 let m = p.start();884 number(p);885 m.complete(p, EXPR_NUMBER)886 } else if p.at(IDENT) {887 let m = p.start();888 name(p);889 m.complete(p, EXPR_VAR)890 } else if p.at(T![if]) {891 let m = p.start();892 p.bump();893 expr(p);894 p.expect(T![then]);895 expr(p).wrap(p, TRUE_EXPR, true);896 if p.at(T![else]) {897 p.bump();898 expr(p).wrap(p, FALSE_EXPR, true);899 }900 m.complete(p, EXPR_IF_THEN_ELSE)901 } else if p.at(T!['[']) {902 array(p)903 } else if p.at(T!['{']) {904 object(p)905 } else if p.at(T![function]) {906 let m = p.start();907 p.bump();908 params_desc(p);909 expr(p);910 m.complete(p, EXPR_FUNCTION)911 } else if p.at(T![error]) {912 let m = p.start();913 p.bump();914 expr(p);915 m.complete(p, EXPR_ERROR)916 } else if p.at(T![import]) || p.at(T![importstr]) || p.at(T![importbin]) {917 let m = p.start();918 p.bump();919 text(p);920 m.complete(p, EXPR_IMPORT)921 } else if let Some(op) = UnaryOperatorKind::cast(p.current()) {922 let ((), right_binding_power) = op.binding_power();923924 let m = p.start();925 p.bump();926 let _ = expr_binding_power(p, right_binding_power)927 .map(|v| v.precede(p).complete(p, EXPR));928 m.complete(p, EXPR_UNARY)929 } else if p.at(T!['(']) {930 let m = p.start();931 p.bump();932 expr(p);933 p.expect(T![')']);934 m.complete(p, EXPR_PARENED)935 } else {936 return Err(p.error_with_no_skip());937 })938}939940impl Parse {941 pub fn syntax(&self) -> SyntaxNode {942 SyntaxNode::new_root(self.green_node.clone())943 }944}crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__local_in_binop_rhs.snapdiffbeforeafterboth--- /dev/null
+++ b/crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__local_in_binop_rhs.snap
@@ -0,0 +1,34 @@
+---
+source: crates/jrsonnet-rowan-parser/src/tests.rs
+expression: "a + local x = 1; x\n"
+---
+SOURCE_FILE@0..19
+ EXPR@0..18
+ EXPR_BINARY@0..18
+ EXPR@0..1
+ EXPR_VAR@0..1
+ NAME@0..1
+ IDENT@0..1 "a"
+ WHITESPACE@1..2 " "
+ PLUS@2..3 "+"
+ WHITESPACE@3..4 " "
+ EXPR@4..18
+ STMT_LOCAL@4..16
+ LOCAL_KW@4..9 "local"
+ WHITESPACE@9..10 " "
+ BIND_DESTRUCT@10..15
+ DESTRUCT_FULL@10..11
+ NAME@10..11
+ IDENT@10..11 "x"
+ WHITESPACE@11..12 " "
+ ASSIGN@12..13 "="
+ WHITESPACE@13..14 " "
+ EXPR@14..15
+ EXPR_NUMBER@14..15
+ FLOAT@14..15 "1"
+ SEMI@15..16 ";"
+ WHITESPACE@16..17 " "
+ EXPR_VAR@17..18
+ NAME@17..18
+ IDENT@17..18 "x"
+ WHITESPACE@18..19 "\n"
crates/jrsonnet-rowan-parser/src/tests.rsdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/src/tests.rs
+++ b/crates/jrsonnet-rowan-parser/src/tests.rs
@@ -224,6 +224,10 @@
unary_not_in_call => r#"
std.assertEqual(!false, true)
"#
+
+ local_in_binop_rhs => r#"
+ a + local x = 1; x
+ "#
);
#[test]