git.delta.rocks / jrsonnet / refs/commits / b1b8b4cf86ba

difftreelog

refactor deduplicate operator definitions

Yaroslav Bolyukin2022-06-20parent: #5ad3c06.patch.diff
in: master

9 files changed

modifiedcrates/jrsonnet-rowan-parser/jsonnet.ungramdiffbeforeafterboth
--- a/crates/jrsonnet-rowan-parser/jsonnet.ungram
+++ b/crates/jrsonnet-rowan-parser/jsonnet.ungram
@@ -136,6 +136,7 @@
 |   '<<' | '>>'
 |   '+' | '-'
 |   '*' | '/' | '%'
+|   'META_OBJECT_APPLY!'
 |   'ERROR_NO_OPERATOR!'
 
 UnaryOperator =
deletedcrates/jrsonnet-rowan-parser/src/binary.rsdiffbeforeafterboth
--- a/crates/jrsonnet-rowan-parser/src/binary.rs
+++ /dev/null
@@ -1,48 +0,0 @@
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
-pub enum BinaryOperator {
-	Mul,
-	Div,
-	Mod,
-	Plus,
-	Minus,
-	ShiftLeft,
-	ShiftRight,
-	LessThan,
-	GreaterThan,
-	LessThanOrEqual,
-	GreaterThanOrEqual,
-	Equal,
-	NotEqual,
-	BitAnd,
-	BitXor,
-	BitOr,
-	And,
-	Or,
-	In,
-	ObjectApply,
-	#[allow(dead_code)]
-	Invalid,
-}
-
-impl BinaryOperator {
-	pub fn binding_power(&self) -> (u8, u8) {
-		match self {
-			Self::ObjectApply => (22, 23),
-			Self::Mul | Self::Div | Self::Mod => (20, 21),
-			Self::Plus | Self::Minus => (18, 19),
-			Self::ShiftLeft | Self::ShiftRight => (16, 17),
-			Self::LessThan
-			| Self::GreaterThan
-			| Self::LessThanOrEqual
-			| Self::GreaterThanOrEqual
-			| Self::In => (14, 15),
-			Self::Equal | Self::NotEqual => (12, 13),
-			Self::BitAnd => (10, 11),
-			Self::BitXor => (8, 9),
-			Self::BitOr => (6, 7),
-			Self::And => (4, 5),
-			Self::Or => (2, 3),
-			Self::Invalid => (0, 1),
-		}
-	}
-}
modifiedcrates/jrsonnet-rowan-parser/src/generated/nodes.rsdiffbeforeafterboth
--- a/crates/jrsonnet-rowan-parser/src/generated/nodes.rs
+++ b/crates/jrsonnet-rowan-parser/src/generated/nodes.rs
@@ -1005,6 +1005,7 @@
 	Mul,
 	Div,
 	Modulo,
+	MetaObjectApply,
 	ErrorNoOperator,
 }
 
@@ -2508,101 +2509,51 @@
 }
 impl AstToken for BinaryOperator {
 	fn can_cast(kind: SyntaxKind) -> bool {
+		BinaryOperatorKind::can_cast(kind)
+	}
+	fn cast(syntax: SyntaxToken) -> Option<Self> {
+		let kind = BinaryOperatorKind::cast(syntax.kind())?;
+		Some(BinaryOperator { syntax, kind })
+	}
+	fn syntax(&self) -> &SyntaxToken {
+		&self.syntax
+	}
+}
+impl BinaryOperatorKind {
+	fn can_cast(kind: SyntaxKind) -> bool {
 		match kind {
 			OR | AND | BIT_OR | BIT_XOR | BIT_AND | EQ | NE | LT | GT | LE | GE | IN_KW | LHS
-			| RHS | PLUS | MINUS | MUL | DIV | MODULO | ERROR_NO_OPERATOR => true,
+			| RHS | PLUS | MINUS | MUL | DIV | MODULO | META_OBJECT_APPLY | ERROR_NO_OPERATOR => true,
 			_ => false,
 		}
 	}
-	fn cast(syntax: SyntaxToken) -> Option<Self> {
-		let res = match syntax.kind() {
-			OR => BinaryOperator {
-				syntax,
-				kind: BinaryOperatorKind::Or,
-			},
-			AND => BinaryOperator {
-				syntax,
-				kind: BinaryOperatorKind::And,
-			},
-			BIT_OR => BinaryOperator {
-				syntax,
-				kind: BinaryOperatorKind::BitOr,
-			},
-			BIT_XOR => BinaryOperator {
-				syntax,
-				kind: BinaryOperatorKind::BitXor,
-			},
-			BIT_AND => BinaryOperator {
-				syntax,
-				kind: BinaryOperatorKind::BitAnd,
-			},
-			EQ => BinaryOperator {
-				syntax,
-				kind: BinaryOperatorKind::Eq,
-			},
-			NE => BinaryOperator {
-				syntax,
-				kind: BinaryOperatorKind::Ne,
-			},
-			LT => BinaryOperator {
-				syntax,
-				kind: BinaryOperatorKind::Lt,
-			},
-			GT => BinaryOperator {
-				syntax,
-				kind: BinaryOperatorKind::Gt,
-			},
-			LE => BinaryOperator {
-				syntax,
-				kind: BinaryOperatorKind::Le,
-			},
-			GE => BinaryOperator {
-				syntax,
-				kind: BinaryOperatorKind::Ge,
-			},
-			IN_KW => BinaryOperator {
-				syntax,
-				kind: BinaryOperatorKind::InKw,
-			},
-			LHS => BinaryOperator {
-				syntax,
-				kind: BinaryOperatorKind::Lhs,
-			},
-			RHS => BinaryOperator {
-				syntax,
-				kind: BinaryOperatorKind::Rhs,
-			},
-			PLUS => BinaryOperator {
-				syntax,
-				kind: BinaryOperatorKind::Plus,
-			},
-			MINUS => BinaryOperator {
-				syntax,
-				kind: BinaryOperatorKind::Minus,
-			},
-			MUL => BinaryOperator {
-				syntax,
-				kind: BinaryOperatorKind::Mul,
-			},
-			DIV => BinaryOperator {
-				syntax,
-				kind: BinaryOperatorKind::Div,
-			},
-			MODULO => BinaryOperator {
-				syntax,
-				kind: BinaryOperatorKind::Modulo,
-			},
-			ERROR_NO_OPERATOR => BinaryOperator {
-				syntax,
-				kind: BinaryOperatorKind::ErrorNoOperator,
-			},
+	pub fn cast(kind: SyntaxKind) -> Option<Self> {
+		let res = match kind {
+			OR => Self::Or,
+			AND => Self::And,
+			BIT_OR => Self::BitOr,
+			BIT_XOR => Self::BitXor,
+			BIT_AND => Self::BitAnd,
+			EQ => Self::Eq,
+			NE => Self::Ne,
+			LT => Self::Lt,
+			GT => Self::Gt,
+			LE => Self::Le,
+			GE => Self::Ge,
+			IN_KW => Self::InKw,
+			LHS => Self::Lhs,
+			RHS => Self::Rhs,
+			PLUS => Self::Plus,
+			MINUS => Self::Minus,
+			MUL => Self::Mul,
+			DIV => Self::Div,
+			MODULO => Self::Modulo,
+			META_OBJECT_APPLY => Self::MetaObjectApply,
+			ERROR_NO_OPERATOR => Self::ErrorNoOperator,
 			_ => return None,
 		};
 		Some(res)
 	}
-	fn syntax(&self) -> &SyntaxToken {
-		&self.syntax
-	}
 }
 impl BinaryOperator {
 	pub fn kind(&self) -> BinaryOperatorKind {
@@ -2616,31 +2567,31 @@
 }
 impl AstToken for UnaryOperator {
 	fn can_cast(kind: SyntaxKind) -> bool {
+		UnaryOperatorKind::can_cast(kind)
+	}
+	fn cast(syntax: SyntaxToken) -> Option<Self> {
+		let kind = UnaryOperatorKind::cast(syntax.kind())?;
+		Some(UnaryOperator { syntax, kind })
+	}
+	fn syntax(&self) -> &SyntaxToken {
+		&self.syntax
+	}
+}
+impl UnaryOperatorKind {
+	fn can_cast(kind: SyntaxKind) -> bool {
 		match kind {
 			MINUS | NOT | BIT_NOT => true,
 			_ => false,
 		}
 	}
-	fn cast(syntax: SyntaxToken) -> Option<Self> {
-		let res = match syntax.kind() {
-			MINUS => UnaryOperator {
-				syntax,
-				kind: UnaryOperatorKind::Minus,
-			},
-			NOT => UnaryOperator {
-				syntax,
-				kind: UnaryOperatorKind::Not,
-			},
-			BIT_NOT => UnaryOperator {
-				syntax,
-				kind: UnaryOperatorKind::BitNot,
-			},
+	pub fn cast(kind: SyntaxKind) -> Option<Self> {
+		let res = match kind {
+			MINUS => Self::Minus,
+			NOT => Self::Not,
+			BIT_NOT => Self::BitNot,
 			_ => return None,
 		};
 		Some(res)
-	}
-	fn syntax(&self) -> &SyntaxToken {
-		&self.syntax
 	}
 }
 impl UnaryOperator {
@@ -2655,44 +2606,35 @@
 }
 impl AstToken for Literal {
 	fn can_cast(kind: SyntaxKind) -> bool {
+		LiteralKind::can_cast(kind)
+	}
+	fn cast(syntax: SyntaxToken) -> Option<Self> {
+		let kind = LiteralKind::cast(syntax.kind())?;
+		Some(Literal { syntax, kind })
+	}
+	fn syntax(&self) -> &SyntaxToken {
+		&self.syntax
+	}
+}
+impl LiteralKind {
+	fn can_cast(kind: SyntaxKind) -> bool {
 		match kind {
 			NULL_KW | TRUE_KW | FALSE_KW | SELF_KW | DOLLAR | SUPER_KW => true,
 			_ => false,
 		}
 	}
-	fn cast(syntax: SyntaxToken) -> Option<Self> {
-		let res = match syntax.kind() {
-			NULL_KW => Literal {
-				syntax,
-				kind: LiteralKind::NullKw,
-			},
-			TRUE_KW => Literal {
-				syntax,
-				kind: LiteralKind::TrueKw,
-			},
-			FALSE_KW => Literal {
-				syntax,
-				kind: LiteralKind::FalseKw,
-			},
-			SELF_KW => Literal {
-				syntax,
-				kind: LiteralKind::SelfKw,
-			},
-			DOLLAR => Literal {
-				syntax,
-				kind: LiteralKind::Dollar,
-			},
-			SUPER_KW => Literal {
-				syntax,
-				kind: LiteralKind::SuperKw,
-			},
+	pub fn cast(kind: SyntaxKind) -> Option<Self> {
+		let res = match kind {
+			NULL_KW => Self::NullKw,
+			TRUE_KW => Self::TrueKw,
+			FALSE_KW => Self::FalseKw,
+			SELF_KW => Self::SelfKw,
+			DOLLAR => Self::Dollar,
+			SUPER_KW => Self::SuperKw,
 			_ => return None,
 		};
 		Some(res)
 	}
-	fn syntax(&self) -> &SyntaxToken {
-		&self.syntax
-	}
 }
 impl Literal {
 	pub fn kind(&self) -> LiteralKind {
@@ -2706,6 +2648,18 @@
 }
 impl AstToken for Text {
 	fn can_cast(kind: SyntaxKind) -> bool {
+		TextKind::can_cast(kind)
+	}
+	fn cast(syntax: SyntaxToken) -> Option<Self> {
+		let kind = TextKind::cast(syntax.kind())?;
+		Some(Text { syntax, kind })
+	}
+	fn syntax(&self) -> &SyntaxToken {
+		&self.syntax
+	}
+}
+impl TextKind {
+	fn can_cast(kind: SyntaxKind) -> bool {
 		match kind {
 			STRING_DOUBLE
 			| ERROR_STRING_DOUBLE_UNTERMINATED
@@ -2724,71 +2678,30 @@
 			_ => false,
 		}
 	}
-	fn cast(syntax: SyntaxToken) -> Option<Self> {
-		let res = match syntax.kind() {
-			STRING_DOUBLE => Text {
-				syntax,
-				kind: TextKind::StringDouble,
-			},
-			ERROR_STRING_DOUBLE_UNTERMINATED => Text {
-				syntax,
-				kind: TextKind::ErrorStringDoubleUnterminated,
-			},
-			STRING_SINGLE => Text {
-				syntax,
-				kind: TextKind::StringSingle,
-			},
-			ERROR_STRING_SINGLE_UNTERMINATED => Text {
-				syntax,
-				kind: TextKind::ErrorStringSingleUnterminated,
-			},
-			STRING_DOUBLE_VERBATIM => Text {
-				syntax,
-				kind: TextKind::StringDoubleVerbatim,
-			},
-			ERROR_STRING_DOUBLE_VERBATIM_UNTERMINATED => Text {
-				syntax,
-				kind: TextKind::ErrorStringDoubleVerbatimUnterminated,
-			},
-			STRING_SINGLE_VERBATIM => Text {
-				syntax,
-				kind: TextKind::StringSingleVerbatim,
-			},
-			ERROR_STRING_SINGLE_VERBATIM_UNTERMINATED => Text {
-				syntax,
-				kind: TextKind::ErrorStringSingleVerbatimUnterminated,
-			},
-			ERROR_STRING_VERBATIM_MISSING_QUOTES => Text {
-				syntax,
-				kind: TextKind::ErrorStringVerbatimMissingQuotes,
-			},
-			STRING_BLOCK => Text {
-				syntax,
-				kind: TextKind::StringBlock,
-			},
-			ERROR_STRING_BLOCK_UNEXPECTED_END => Text {
-				syntax,
-				kind: TextKind::ErrorStringBlockUnexpectedEnd,
-			},
-			ERROR_STRING_BLOCK_MISSING_NEW_LINE => Text {
-				syntax,
-				kind: TextKind::ErrorStringBlockMissingNewLine,
-			},
-			ERROR_STRING_BLOCK_MISSING_TERMINATION => Text {
-				syntax,
-				kind: TextKind::ErrorStringBlockMissingTermination,
-			},
-			ERROR_STRING_BLOCK_MISSING_INDENT => Text {
-				syntax,
-				kind: TextKind::ErrorStringBlockMissingIndent,
-			},
+	pub fn cast(kind: SyntaxKind) -> Option<Self> {
+		let res = match kind {
+			STRING_DOUBLE => Self::StringDouble,
+			ERROR_STRING_DOUBLE_UNTERMINATED => Self::ErrorStringDoubleUnterminated,
+			STRING_SINGLE => Self::StringSingle,
+			ERROR_STRING_SINGLE_UNTERMINATED => Self::ErrorStringSingleUnterminated,
+			STRING_DOUBLE_VERBATIM => Self::StringDoubleVerbatim,
+			ERROR_STRING_DOUBLE_VERBATIM_UNTERMINATED => {
+				Self::ErrorStringDoubleVerbatimUnterminated
+			}
+			STRING_SINGLE_VERBATIM => Self::StringSingleVerbatim,
+			ERROR_STRING_SINGLE_VERBATIM_UNTERMINATED => {
+				Self::ErrorStringSingleVerbatimUnterminated
+			}
+			ERROR_STRING_VERBATIM_MISSING_QUOTES => Self::ErrorStringVerbatimMissingQuotes,
+			STRING_BLOCK => Self::StringBlock,
+			ERROR_STRING_BLOCK_UNEXPECTED_END => Self::ErrorStringBlockUnexpectedEnd,
+			ERROR_STRING_BLOCK_MISSING_NEW_LINE => Self::ErrorStringBlockMissingNewLine,
+			ERROR_STRING_BLOCK_MISSING_TERMINATION => Self::ErrorStringBlockMissingTermination,
+			ERROR_STRING_BLOCK_MISSING_INDENT => Self::ErrorStringBlockMissingIndent,
 			_ => return None,
 		};
 		Some(res)
 	}
-	fn syntax(&self) -> &SyntaxToken {
-		&self.syntax
-	}
 }
 impl Text {
 	pub fn kind(&self) -> TextKind {
@@ -2802,6 +2715,18 @@
 }
 impl AstToken for Number {
 	fn can_cast(kind: SyntaxKind) -> bool {
+		NumberKind::can_cast(kind)
+	}
+	fn cast(syntax: SyntaxToken) -> Option<Self> {
+		let kind = NumberKind::cast(syntax.kind())?;
+		Some(Number { syntax, kind })
+	}
+	fn syntax(&self) -> &SyntaxToken {
+		&self.syntax
+	}
+}
+impl NumberKind {
+	fn can_cast(kind: SyntaxKind) -> bool {
 		match kind {
 			FLOAT
 			| ERROR_FLOAT_JUNK_AFTER_POINT
@@ -2810,31 +2735,16 @@
 			_ => false,
 		}
 	}
-	fn cast(syntax: SyntaxToken) -> Option<Self> {
-		let res = match syntax.kind() {
-			FLOAT => Number {
-				syntax,
-				kind: NumberKind::Float,
-			},
-			ERROR_FLOAT_JUNK_AFTER_POINT => Number {
-				syntax,
-				kind: NumberKind::ErrorFloatJunkAfterPoint,
-			},
-			ERROR_FLOAT_JUNK_AFTER_EXPONENT => Number {
-				syntax,
-				kind: NumberKind::ErrorFloatJunkAfterExponent,
-			},
-			ERROR_FLOAT_JUNK_AFTER_EXPONENT_SIGN => Number {
-				syntax,
-				kind: NumberKind::ErrorFloatJunkAfterExponentSign,
-			},
+	pub fn cast(kind: SyntaxKind) -> Option<Self> {
+		let res = match kind {
+			FLOAT => Self::Float,
+			ERROR_FLOAT_JUNK_AFTER_POINT => Self::ErrorFloatJunkAfterPoint,
+			ERROR_FLOAT_JUNK_AFTER_EXPONENT => Self::ErrorFloatJunkAfterExponent,
+			ERROR_FLOAT_JUNK_AFTER_EXPONENT_SIGN => Self::ErrorFloatJunkAfterExponentSign,
 			_ => return None,
 		};
 		Some(res)
 	}
-	fn syntax(&self) -> &SyntaxToken {
-		&self.syntax
-	}
 }
 impl Number {
 	pub fn kind(&self) -> NumberKind {
@@ -2848,32 +2758,32 @@
 }
 impl AstToken for ImportKind {
 	fn can_cast(kind: SyntaxKind) -> bool {
+		ImportKindKind::can_cast(kind)
+	}
+	fn cast(syntax: SyntaxToken) -> Option<Self> {
+		let kind = ImportKindKind::cast(syntax.kind())?;
+		Some(ImportKind { syntax, kind })
+	}
+	fn syntax(&self) -> &SyntaxToken {
+		&self.syntax
+	}
+}
+impl ImportKindKind {
+	fn can_cast(kind: SyntaxKind) -> bool {
 		match kind {
 			IMPORTSTR_KW | IMPORTBIN_KW | IMPORT_KW => true,
 			_ => false,
 		}
 	}
-	fn cast(syntax: SyntaxToken) -> Option<Self> {
-		let res = match syntax.kind() {
-			IMPORTSTR_KW => ImportKind {
-				syntax,
-				kind: ImportKindKind::ImportstrKw,
-			},
-			IMPORTBIN_KW => ImportKind {
-				syntax,
-				kind: ImportKindKind::ImportbinKw,
-			},
-			IMPORT_KW => ImportKind {
-				syntax,
-				kind: ImportKindKind::ImportKw,
-			},
+	pub fn cast(kind: SyntaxKind) -> Option<Self> {
+		let res = match kind {
+			IMPORTSTR_KW => Self::ImportstrKw,
+			IMPORTBIN_KW => Self::ImportbinKw,
+			IMPORT_KW => Self::ImportKw,
 			_ => return None,
 		};
 		Some(res)
 	}
-	fn syntax(&self) -> &SyntaxToken {
-		&self.syntax
-	}
 }
 impl ImportKind {
 	pub fn kind(&self) -> ImportKindKind {
@@ -2887,31 +2797,31 @@
 }
 impl AstToken for Visibility {
 	fn can_cast(kind: SyntaxKind) -> bool {
+		VisibilityKind::can_cast(kind)
+	}
+	fn cast(syntax: SyntaxToken) -> Option<Self> {
+		let kind = VisibilityKind::cast(syntax.kind())?;
+		Some(Visibility { syntax, kind })
+	}
+	fn syntax(&self) -> &SyntaxToken {
+		&self.syntax
+	}
+}
+impl VisibilityKind {
+	fn can_cast(kind: SyntaxKind) -> bool {
 		match kind {
 			COLONCOLONCOLON | COLONCOLON | COLON => true,
 			_ => false,
 		}
 	}
-	fn cast(syntax: SyntaxToken) -> Option<Self> {
-		let res = match syntax.kind() {
-			COLONCOLONCOLON => Visibility {
-				syntax,
-				kind: VisibilityKind::Coloncoloncolon,
-			},
-			COLONCOLON => Visibility {
-				syntax,
-				kind: VisibilityKind::Coloncolon,
-			},
-			COLON => Visibility {
-				syntax,
-				kind: VisibilityKind::Colon,
-			},
+	pub fn cast(kind: SyntaxKind) -> Option<Self> {
+		let res = match kind {
+			COLONCOLONCOLON => Self::Coloncoloncolon,
+			COLONCOLON => Self::Coloncolon,
+			COLON => Self::Colon,
 			_ => return None,
 		};
 		Some(res)
-	}
-	fn syntax(&self) -> &SyntaxToken {
-		&self.syntax
 	}
 }
 impl Visibility {
@@ -2926,6 +2836,18 @@
 }
 impl AstToken for Trivia {
 	fn can_cast(kind: SyntaxKind) -> bool {
+		TriviaKind::can_cast(kind)
+	}
+	fn cast(syntax: SyntaxToken) -> Option<Self> {
+		let kind = TriviaKind::cast(syntax.kind())?;
+		Some(Trivia { syntax, kind })
+	}
+	fn syntax(&self) -> &SyntaxToken {
+		&self.syntax
+	}
+}
+impl TriviaKind {
+	fn can_cast(kind: SyntaxKind) -> bool {
 		match kind {
 			WHITESPACE
 			| MULTI_LINE_COMMENT
@@ -2936,38 +2858,17 @@
 			_ => false,
 		}
 	}
-	fn cast(syntax: SyntaxToken) -> Option<Self> {
-		let res = match syntax.kind() {
-			WHITESPACE => Trivia {
-				syntax,
-				kind: TriviaKind::Whitespace,
-			},
-			MULTI_LINE_COMMENT => Trivia {
-				syntax,
-				kind: TriviaKind::MultiLineComment,
-			},
-			ERROR_COMMENT_TOO_SHORT => Trivia {
-				syntax,
-				kind: TriviaKind::ErrorCommentTooShort,
-			},
-			ERROR_COMMENT_UNTERMINATED => Trivia {
-				syntax,
-				kind: TriviaKind::ErrorCommentUnterminated,
-			},
-			SINGLE_LINE_HASH_COMMENT => Trivia {
-				syntax,
-				kind: TriviaKind::SingleLineHashComment,
-			},
-			SINGLE_LINE_SLASH_COMMENT => Trivia {
-				syntax,
-				kind: TriviaKind::SingleLineSlashComment,
-			},
+	pub fn cast(kind: SyntaxKind) -> Option<Self> {
+		let res = match kind {
+			WHITESPACE => Self::Whitespace,
+			MULTI_LINE_COMMENT => Self::MultiLineComment,
+			ERROR_COMMENT_TOO_SHORT => Self::ErrorCommentTooShort,
+			ERROR_COMMENT_UNTERMINATED => Self::ErrorCommentUnterminated,
+			SINGLE_LINE_HASH_COMMENT => Self::SingleLineHashComment,
+			SINGLE_LINE_SLASH_COMMENT => Self::SingleLineSlashComment,
 			_ => return None,
 		};
 		Some(res)
-	}
-	fn syntax(&self) -> &SyntaxToken {
-		&self.syntax
 	}
 }
 impl Trivia {
modifiedcrates/jrsonnet-rowan-parser/src/generated/syntax_kinds.rsdiffbeforeafterboth
--- a/crates/jrsonnet-rowan-parser/src/generated/syntax_kinds.rs
+++ b/crates/jrsonnet-rowan-parser/src/generated/syntax_kinds.rs
@@ -163,6 +163,7 @@
 	ERROR_KW,
 	#[token("in")]
 	IN_KW,
+	META_OBJECT_APPLY,
 	ERROR_NO_OPERATOR,
 	#[token("null")]
 	NULL_KW,
modifiedcrates/jrsonnet-rowan-parser/src/lib.rsdiffbeforeafterboth
--- a/crates/jrsonnet-rowan-parser/src/lib.rs
+++ b/crates/jrsonnet-rowan-parser/src/lib.rs
@@ -1,17 +1,16 @@
 #![deny(unused_must_use)]
 
 mod ast;
-mod binary;
 mod event;
 mod generated;
 mod language;
 mod lex;
 mod marker;
 mod parser;
+mod precedence;
 mod string_block;
 mod tests;
 mod token_set;
-mod unary;
 
 pub use ast::{AstChildren, AstNode, AstToken};
 use event::Sink;
modifiedcrates/jrsonnet-rowan-parser/src/parser.rsdiffbeforeafterboth
before · crates/jrsonnet-rowan-parser/src/parser.rs
1use std::{cell::Cell, fmt::Display, rc::Rc};23use miette::{LabeledSpan, SourceOffset, SourceSpan};4use rowan::{GreenNode, TextRange, TextSize};56use crate::{7	binary::BinaryOperator,8	event::Event,9	lex::Lexeme,10	marker::{AsRange, CompletedMarker, Marker, Ranger},11	nodes::{Literal, Number, Text, Trivia},12	token_set::SyntaxKindSet,13	unary::UnaryOperator,14	AstToken, SyntaxKind,15	SyntaxKind::*,16	SyntaxNode, T, TS,17};1819pub struct Parse {20	pub green_node: GreenNode,21	pub errors: Vec<SyntaxError>,22}2324#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]25pub enum ExpectedSyntax {26	Named(&'static str),27	Unnamed(SyntaxKind),28}29impl Display for ExpectedSyntax {30	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {31		match self {32			ExpectedSyntax::Named(n) => write!(f, "{}", n),33			ExpectedSyntax::Unnamed(u) => write!(f, "{:?}", u),34		}35	}36}3738pub struct Parser<'i> {39	// TODO: remove all trivia before feeding to parser?40	lexemes: &'i [Lexeme<'i>],41	pub offset: usize,42	pub events: Vec<Event>,43	pub entered: u32,44	pub hints: Vec<(u32, TextRange, String)>,45	pub last_error_token: usize,46	expected_syntax: Option<ExpectedSyntax>,47	expected_syntax_tracking_state: Rc<Cell<ExpectedSyntaxTrackingState>>,48	steps: Cell<u64>,49}5051const DEFAULT_RECOVERY_SET: SyntaxKindSet = TS![];5253#[derive(Clone, Debug, PartialEq, Eq)]54pub enum SyntaxError {55	Unexpected {56		expected: ExpectedSyntax,57		found: SyntaxKind,58		range: TextRange,59	},60	Missing {61		expected: ExpectedSyntax,62		offset: TextSize,63	},64	Custom {65		error: String,66		range: TextRange,67	},68	Hint {69		error: String,70		range: TextRange,71	},72}7374impl From<SyntaxError> for LabeledSpan {75	fn from(val: SyntaxError) -> Self {76		match val {77			SyntaxError::Unexpected {78				expected,79				found,80				range,81			} => LabeledSpan::new_with_span(82				Some(format!("expected {}, found {:?}", expected, found)),83				SourceSpan::new(84					SourceOffset::from(usize::from(range.start())),85					SourceOffset::from(usize::from(range.end() - range.start())),86				),87			),88			SyntaxError::Missing { expected, offset } => LabeledSpan::new_with_span(89				Some(format!("missing {}", expected)),90				SourceSpan::new(91					SourceOffset::from(usize::from(offset)),92					SourceOffset::from(0),93				),94			),95			SyntaxError::Custom { error, range } | SyntaxError::Hint { error, range } => {96				LabeledSpan::new_with_span(97					Some(error),98					SourceSpan::new(99						SourceOffset::from(usize::from(range.start())),100						SourceOffset::from(usize::from(range.end() - range.start())),101					),102				)103			}104		}105	}106}107108impl<'i> Parser<'i> {109	pub fn new(lexemes: &'i [Lexeme<'i>]) -> Self {110		Self {111			lexemes,112			offset: 0,113			events: vec![],114			entered: 0,115			last_error_token: 0,116			hints: vec![],117			expected_syntax: None,118			expected_syntax_tracking_state: Rc::new(Cell::new(119				ExpectedSyntaxTrackingState::Unnamed,120			)),121			steps: Cell::new(0),122		}123	}124	pub fn clear_outdated_hints(&mut self) {125		let amount = self126			.hints127			.iter()128			.rev()129			.take_while(|h| h.0 > self.entered)130			.count();131		self.hints.truncate(self.hints.len() - amount)132	}133	fn clear_expected_syntaxes(&mut self) {134		self.expected_syntax = None;135		self.expected_syntax_tracking_state136			.set(ExpectedSyntaxTrackingState::Unnamed);137	}138	pub fn start(&mut self) -> Marker {139		self.skip_trivia();140		let start_event_idx = self.events.len();141		self.events.push(Event::Pending);142		self.entered += 1;143		Marker::new(start_event_idx)144	}145	pub fn start_ranger(&mut self) -> Ranger {146		self.skip_trivia();147		let pos = self.offset;148		Ranger { pos }149	}150	pub fn parse(mut self) -> Vec<Event> {151		let m = self.start();152		expr(&mut self);153		self.expect(EOF);154		m.complete(&mut self, SOURCE_FILE);155156		self.events157	}158159	pub(crate) fn expect(&mut self, kind: SyntaxKind) {160		self.expect_with_recovery_set(kind, TS![])161	}162163	pub(crate) fn expect_with_recovery_set(164		&mut self,165		kind: SyntaxKind,166		recovery_set: SyntaxKindSet,167	) {168		if self.at(kind) {169			if kind != EOF {170				self.bump();171			}172		} else {173			self.error_with_recovery_set(recovery_set);174		}175	}176177	pub(crate) fn expect_with_no_skip(&mut self, kind: SyntaxKind) {178		if self.at(kind) {179			self.bump();180		} else {181			self.error_with_no_skip();182		}183	}184	fn current_token(&self) -> Lexeme<'i> {185		self.lexemes[self.offset]186	}187	fn previous_token(&mut self) -> Option<Lexeme<'i>> {188		if self.offset == 0 {189			return None;190		}191		let mut previous_token_idx = self.offset - 1;192		while self193			.lexemes194			.get(previous_token_idx)195			.map_or(false, |l| Trivia::can_cast(l.kind))196			&& previous_token_idx != 0197		{198			previous_token_idx -= 1;199		}200201		Some(self.lexemes[previous_token_idx])202	}203	pub fn start_of_token(&self, mut idx: usize) -> TextSize {204		while Trivia::can_cast(self.lexemes[idx].kind) {205			idx += 1;206		}207		self.lexemes[idx].range.start()208	}209	pub fn end_of_token(&self, mut idx: usize) -> TextSize {210		while Trivia::can_cast(self.lexemes[idx].kind) {211			idx -= 1;212		}213		self.lexemes[idx].range.end()214	}215	pub(crate) fn custom_error(&mut self, marker: impl AsRange, error: impl AsRef<str>) {216		self.last_error_token = marker.end_token();217		self.events.push(Event::Error(SyntaxError::Custom {218			error: error.as_ref().to_string(),219			range: marker.as_range(self),220		}));221	}222	pub(crate) fn error_with_recovery_set(223		&mut self,224		recovery_set: SyntaxKindSet,225	) -> Option<CompletedMarker> {226		self.error_with_recovery_set_no_default(recovery_set.union(DEFAULT_RECOVERY_SET))227	}228	pub fn error_with_no_skip(&mut self) -> Option<CompletedMarker> {229		self.error_with_recovery_set_no_default(SyntaxKindSet::ALL)230	}231232	pub fn error_with_recovery_set_no_default(233		&mut self,234		recovery_set: SyntaxKindSet,235	) -> Option<CompletedMarker> {236		let expected_syntax = self237			.expected_syntax238			.take()239			.unwrap_or(ExpectedSyntax::Named("unknown"));240		self.expected_syntax_tracking_state241			.set(ExpectedSyntaxTrackingState::Unnamed);242243		self.skip_trivia();244		if self.at_end() || self.at_ts(recovery_set) {245			let range = self246				.previous_token()247				.map(|t| t.range)248				.unwrap_or_else(|| TextRange::at(TextSize::from(0), TextSize::from(0)));249250			self.events.push(Event::Error(SyntaxError::Missing {251				expected: expected_syntax,252				offset: range.end(),253			}));254			return None;255		}256257		let current_token = self.current_token();258259		self.events.push(Event::Error(SyntaxError::Unexpected {260			expected: expected_syntax,261			found: current_token.kind,262			range: current_token.range,263		}));264		self.clear_expected_syntaxes();265		self.last_error_token = self.offset;266267		let m = self.start();268		self.bump();269		Some(m.complete(self, SyntaxKind::ERROR))270	}271	fn bump_assert(&mut self, kind: SyntaxKind) {272		self.skip_trivia();273		assert!(self.at(kind), "expected {:?}", kind);274		self.bump_remap(self.current());275	}276	fn bump(&mut self) {277		self.skip_trivia();278		self.bump_remap(self.current());279	}280	fn bump_remap(&mut self, kind: SyntaxKind) {281		self.skip_trivia();282		assert_ne!(self.offset, self.lexemes.len(), "already at end");283		self.events.push(Event::Token { kind });284		self.offset += 1;285		self.clear_expected_syntaxes();286	}287	fn step(&self) {288		use std::fmt::Write;289		let steps = self.steps.get();290		if steps >= 15000000 {291			let mut out = "seems like parsing is stuck".to_owned();292			{293				let last = 20;294				write!(out, "\n\nLast {} events:", last).unwrap();295				for (i, event) in self296					.events297					.iter()298					.skip(self.events.len().saturating_sub(last))299					.enumerate()300				{301					write!(out, "\n{i}. {event:?}").unwrap();302				}303			}304			{305				let next = 20;306				write!(out, "\n\nNext {next} tokens:").unwrap();307				for (i, tok) in self.lexemes.iter().skip(self.offset).take(next).enumerate() {308					write!(out, "\n{i}. {tok:?}").unwrap();309				}310			}311			panic!("{out}")312		}313		self.steps.set(steps + 1);314	}315	fn nth(&self, i: usize) -> SyntaxKind {316		self.step();317		let mut offset = self.offset;318		for _ in 0..i {319			while self320				.lexemes321				.get(offset)322				.map(|l| Trivia::can_cast(l.kind))323				.unwrap_or(false)324			{325				offset += 1;326			}327			offset += 1;328		}329		while self330			.lexemes331			.get(offset)332			.map(|l| Trivia::can_cast(l.kind))333			.unwrap_or(false)334		{335			offset += 1;336		}337		self.lexemes.get(offset).map(|l| l.kind).unwrap_or(EOF)338	}339	fn current(&self) -> SyntaxKind {340		self.nth(0)341	}342	fn skip_trivia(&mut self) {343		while Trivia::can_cast(self.peek_raw()) {344			self.offset += 1;345		}346	}347	fn peek_raw(&mut self) -> SyntaxKind {348		self.lexemes349			.get(self.offset)350			.map(|l| l.kind)351			.unwrap_or(SyntaxKind::EOF)352	}353	#[must_use]354	pub(crate) fn expected_syntax_name(&mut self, name: &'static str) -> ExpectedSyntaxGuard {355		self.expected_syntax_tracking_state356			.set(ExpectedSyntaxTrackingState::Named);357		self.expected_syntax = Some(ExpectedSyntax::Named(name));358359		ExpectedSyntaxGuard::new(Rc::clone(&self.expected_syntax_tracking_state))360	}361	pub fn at(&mut self, kind: SyntaxKind) -> bool {362		self.nth_at(0, kind)363	}364	pub fn nth_at(&mut self, n: usize, kind: SyntaxKind) -> bool {365		if let ExpectedSyntaxTrackingState::Unnamed = self.expected_syntax_tracking_state.get() {366			self.expected_syntax = Some(ExpectedSyntax::Unnamed(kind));367		}368		self.nth(n) == kind369	}370	pub fn at_ts(&mut self, set: SyntaxKindSet) -> bool {371		set.contains(self.current())372	}373	pub fn at_end(&mut self) -> bool {374		self.at(EOF)375	}376}377pub(crate) struct ExpectedSyntaxGuard {378	expected_syntax_tracking_state: Rc<Cell<ExpectedSyntaxTrackingState>>,379}380381impl ExpectedSyntaxGuard {382	fn new(expected_syntax_tracking_state: Rc<Cell<ExpectedSyntaxTrackingState>>) -> Self {383		Self {384			expected_syntax_tracking_state,385		}386	}387}388389impl Drop for ExpectedSyntaxGuard {390	fn drop(&mut self) {391		self.expected_syntax_tracking_state392			.set(ExpectedSyntaxTrackingState::Unnamed);393	}394}395396#[derive(Debug, Clone, Copy)]397enum ExpectedSyntaxTrackingState {398	Named,399	Unnamed,400}401macro_rules! at_match {402	($p:ident {403		$($r:expr => $e:expr,)*404		_ => $else:expr $(,)?405	}) => {{406		$(407			if $p.at($r) {$e} else408		)* {409			$else410		}411	}}412}413414fn expr(p: &mut Parser) -> Option<CompletedMarker> {415	expr_binding_power(p, 0)416}417fn expr_binding_power(p: &mut Parser, minimum_binding_power: u8) -> Option<CompletedMarker> {418	let mut lhs = lhs(p)?;419420	loop {421		let op = at_match!(p {422			T![*] => BinaryOperator::Mul,423			T![/] => BinaryOperator::Div,424			T![%] => BinaryOperator::Mod,425			T![+] => BinaryOperator::Plus,426			T![-] => BinaryOperator::Minus,427			T![<<] => BinaryOperator::ShiftLeft,428			T![>>] => BinaryOperator::ShiftRight,429			T![<] => BinaryOperator::LessThan,430			T![>] => BinaryOperator::GreaterThan,431			T![<=] => BinaryOperator::LessThanOrEqual,432			T![>=] => BinaryOperator::GreaterThanOrEqual,433			T![==] => BinaryOperator::Equal,434			T![!=] => BinaryOperator::NotEqual,435			T![&] => BinaryOperator::BitAnd,436			T![^] => BinaryOperator::BitXor,437			T![|] => BinaryOperator::BitOr,438			T![&&] => BinaryOperator::And,439			T![||] => BinaryOperator::Or,440			T![in] => BinaryOperator::In,441			T!['{'] => BinaryOperator::ObjectApply,442			_ => break,443		});444		let (left_binding_power, right_binding_power) = op.binding_power();445		if left_binding_power < minimum_binding_power {446			break;447		}448449		// Object apply is not a real operator, we dont have something to bump450		if op != BinaryOperator::ObjectApply {451			p.bump();452		}453454		let m = lhs.wrap(p, LHS_EXPR).precede(p);455		let parsed_rhs = expr_binding_power(p, right_binding_power).is_some();456		lhs = m.complete(457			p,458			if op == BinaryOperator::ObjectApply {459				EXPR_OBJ_EXTEND460			} else {461				EXPR_BINARY462			},463		);464465		if !parsed_rhs {466			break;467		}468	}469	Some(lhs)470}471fn compspec(p: &mut Parser) {472	assert!(p.at(T![for]) || p.at(T![if]));473	if p.at(T![for]) {474		let m = p.start();475		p.bump();476		name(p);477		p.expect(T![in]);478		expr(p);479		m.complete(p, FOR_SPEC);480	} else if p.at(T![if]) {481		let m = p.start();482		p.bump();483		expr(p);484		m.complete(p, IF_SPEC);485	} else {486		unreachable!()487	}488}489fn comma(p: &mut Parser) -> bool {490	if p.at(T![,]) {491		p.bump();492		true493	} else {494		false495	}496}497fn comma_with_alternatives(p: &mut Parser, set: SyntaxKindSet) -> bool {498	if p.at(T![,]) {499		p.bump();500		true501	} else if p.at_ts(set) {502		p.expect_with_no_skip(T![,]);503		p.bump();504		true505	} else {506		false507	}508}509fn field_name(p: &mut Parser) {510	let _e = p.expected_syntax_name("field name");511	let m = p.start();512	if p.at(T!['[']) {513		p.bump();514		expr(p);515		p.expect(T![']']);516		m.complete(p, FIELD_NAME_DYNAMIC);517	} else if p.at(IDENT) {518		name(p);519		m.complete(p, FIELD_NAME_FIXED);520	} else if Text::can_cast(p.current()) {521		text(p);522		m.complete(p, FIELD_NAME_FIXED);523	} else {524		p.error_with_recovery_set(TS![;]);525	}526}527fn visibility(p: &mut Parser) {528	if p.at_ts(TS![: :: :::]) {529		p.bump()530	} else {531		p.error_with_recovery_set(TS![]);532	}533}534fn field(p: &mut Parser) {535	let m = p.start();536	field_name(p);537	let plus = if p.at(T![+]) {538		let r = p.start_ranger();539		p.bump();540		Some(r.finish(p))541	} else {542		None543	};544	let params = if p.at(T!['(']) {545		if let Some(plus) = plus {546			p.custom_error(plus, "can't extend with method");547		}548		params_desc(p);549		if p.at(T![+]) {550			let r = p.start_ranger();551			p.bump();552			p.custom_error(r.finish(p), "can't extend with method");553		}554		true555	} else {556		false557	};558	visibility(p);559	expr(p);560561	if params {562		m.complete(p, FIELD_METHOD)563	} else {564		m.complete(p, FIELD_NORMAL)565	};566}567fn assertion(p: &mut Parser) {568	let m = p.start();569	p.bump_assert(T![assert]);570	expr(p).map(|c| c.wrap(p, LHS_EXPR));571	if p.at(T![:]) {572		p.bump();573		expr(p);574	}575	m.complete(p, ASSERTION);576}577fn object(p: &mut Parser) -> CompletedMarker {578	let m_t = p.start();579	let m = p.start();580	p.bump_assert(T!['{']);581582	loop {583		if p.at(T!['}']) {584			p.bump();585			break;586		}587		let m = p.start();588		if p.at(T![local]) {589			obj_local(p);590			m.complete(p, MEMBER_BIND_STMT)591		} else if p.at(T![assert]) {592			assertion(p);593			m.complete(p, MEMBER_ASSERT_STMT)594		} else {595			field(p);596			while p.at(T![for]) || p.at(T![if]) {597				compspec(p)598			}599			m.complete(p, MEMBER_FIELD)600		};601		if comma_with_alternatives(p, SyntaxKindSet::new(&[T![=]])) {602			continue;603		}604		p.expect(R_BRACE);605		break;606	}607608	m.complete(p, OBJ_BODY_MEMBER_LIST);609	m_t.complete(p, EXPR_OBJECT)610}611fn param(p: &mut Parser) {612	let m = p.start();613	destruct(p);614	if p.at(T![=]) {615		p.bump();616		expr(p);617	}618	m.complete(p, PARAM);619}620fn params_desc(p: &mut Parser) -> CompletedMarker {621	let m = p.start();622	p.bump_assert(T!['(']);623624	loop {625		if p.at(T![')']) {626			p.bump();627			break;628		}629		param(p);630		if comma(p) {631			continue;632		}633		p.expect(T![')']);634		break;635	}636637	m.complete(p, PARAMS_DESC)638}639fn args_desc(p: &mut Parser) {640	let m = p.start();641	p.bump_assert(T!['(']);642643	let started_named = Cell::new(false);644645	loop {646		if p.at(T![')']) {647			break;648		}649650		let m = p.start();651		if p.at(IDENT) && p.nth_at(1, T![=]) {652			name(p);653			p.bump();654			expr(p);655			m.complete(p, ARG);656			started_named.set(true);657		} else {658			expr(p);659			m.complete(p, ARG);660		}661		if comma(p) {662			continue;663		}664		break;665	}666	p.expect(T![')']);667	if p.at(T![tailstrict]) {668		p.bump()669	}670	m.complete(p, ARGS_DESC);671}672673fn array(p: &mut Parser) -> CompletedMarker {674	// Start the list node675	let m = p.start();676	p.bump_assert(T!['[']);677678	// This vec will have at most one element in case of correct input679	let mut compspecs = Vec::with_capacity(1);680	let mut elems = 0;681682	loop {683		if p.at(T![']']) {684			p.bump();685			break;686		}687		elems += 1;688		expr(p);689		let c = p.start_ranger();690		let mut had_spec = false;691		while p.at(T![for]) || p.at(T![if]) {692			had_spec = true;693			compspec(p)694		}695		if had_spec {696			compspecs.push(c.finish(p));697		}698		if comma(p) {699			continue;700		}701		p.expect(T![']']);702		break;703	}704705	if elems > 1 && !compspecs.is_empty() {706		for spec in compspecs {707			p.custom_error(708				spec,709				"compspec may only be used if there is only one array element",710			)711		}712713		m.complete(p, EXPR_ARRAY)714	} else if !compspecs.is_empty() {715		m.complete(p, EXPR_ARRAY_COMP)716	} else {717		m.complete(p, EXPR_ARRAY)718	}719}720/// Returns true if it was slice, false if just index721#[must_use]722fn slice_desc_or_index(p: &mut Parser) -> bool {723	let m = p.start();724	p.bump();725	// TODO: do not treat :, ::, ::: as full tokens?726	// Start727	if !p.at(T![:]) && !p.at(T![::]) {728		expr(p);729	}730	if p.at(T![:]) {731		p.bump();732		// End733		if !p.at(T![']']) {734			expr(p).map(|c| c.wrap(p, SLICE_DESC_END));735		}736		if p.at(T![:]) {737			p.bump();738			// Step739			if !p.at(T![']']) {740				expr(p).map(|c| c.wrap(p, SLICE_DESC_STEP));741			}742		}743	} else if p.at(T![::]) {744		p.bump();745		// End746		if !p.at(T![']']) {747			expr(p).map(|c| c.wrap(p, SLICE_DESC_END));748		}749	} else {750		// It was not a slice751		p.expect(T![']']);752		m.forget(p);753		return false;754	}755	p.expect(T![']']);756	m.complete(p, SLICE_DESC);757	true758}759fn lhs(p: &mut Parser) -> Option<CompletedMarker> {760	let mut lhs = lhs_basic(p)?;761762	loop {763		if p.at(T![.]) {764			let m = lhs.precede(p);765			p.bump();766			name(p);767			lhs = m.complete(p, EXPR_INDEX);768		} else if p.at(T!['[']) {769			if slice_desc_or_index(p) {770				lhs = lhs.precede(p).complete(p, EXPR_SLICE);771			} else {772				lhs = lhs773					.wrap(p, LHS_EXPR)774					.precede(p)775					.complete(p, EXPR_INDEX_EXPR);776			}777		} else if p.at(T!['(']) {778			let m = lhs.precede(p);779			args_desc(p);780			lhs = m.complete(p, EXPR_APPLY);781		} else {782			break;783		}784	}785786	Some(lhs)787}788fn name(p: &mut Parser) {789	let m = p.start();790	p.expect(IDENT);791	m.complete(p, NAME);792}793fn destruct_rest(p: &mut Parser) {794	let m = p.start();795	p.bump_assert(T![...]);796	if p.at(IDENT) {797		p.bump()798	}799	m.complete(p, DESTRUCT_REST);800}801fn destruct_object_field(p: &mut Parser) {802	let m = p.start();803	name(p);804	if p.at(T![:]) {805		p.bump();806		destruct(p);807	};808	if p.at(T![=]) {809		p.bump();810		expr(p);811	}812	m.complete(p, DESTRUCT_OBJECT_FIELD);813}814fn obj_local(p: &mut Parser) {815	let m = p.start();816	p.bump_assert(T![local]);817	bind(p);818	m.complete(p, OBJ_LOCAL);819}820fn destruct(p: &mut Parser) -> CompletedMarker {821	let m = p.start();822	if p.at(T![?]) {823		p.bump();824		m.complete(p, DESTRUCT_SKIP)825	} else if p.at(T!['[']) {826		p.bump();827		let mut had_rest = false;828		loop {829			if p.at(T![']']) {830				p.bump();831				break;832			} else if p.at(T![...]) {833				let m_err = p.start_ranger();834				destruct_rest(p);835				if had_rest {836					p.custom_error(m_err.finish(p), "only one rest can be present in array");837				}838				had_rest = true;839			} else {840				destruct(p);841			}842			if p.at(T![,]) {843				p.bump();844				continue;845			}846			p.expect(T![']']);847			break;848		}849		m.complete(p, DESTRUCT_ARRAY)850	} else if p.at(T!['{']) {851		p.bump();852		let mut had_rest = false;853		loop {854			if p.at(T!['}']) {855				p.bump();856				break;857			} else if p.at(T![...]) {858				let m_err = p.start_ranger();859				destruct_rest(p);860				if had_rest {861					p.custom_error(m_err.finish(p), "only one rest can be present in object");862				}863				had_rest = true;864			} else {865				if had_rest {866					p.error_with_recovery_set(TS![]);867				}868				destruct_object_field(p);869			}870			if p.at(T![,]) {871				p.bump();872				continue;873			}874			p.expect(T!['}']);875			break;876		}877		m.complete(p, DESTRUCT_OBJECT)878	} else if p.at(IDENT) {879		name(p);880		m.complete(p, DESTRUCT_FULL)881	} else {882		m.complete(p, ERROR)883	}884}885fn bind(p: &mut Parser) {886	let m = p.start();887	if p.at(IDENT) && p.nth_at(1, T!['(']) {888		name(p);889		params_desc(p);890		p.expect(T![=]);891		expr(p);892		m.complete(p, BIND_FUNCTION)893	} else {894		destruct(p);895		p.expect(T![=]);896		expr(p);897		m.complete(p, BIND_DESTRUCT)898	};899}900fn text(p: &mut Parser) {901	assert!(Text::can_cast(p.current()));902	p.bump();903}904fn number(p: &mut Parser) {905	assert!(Number::can_cast(p.current()));906	p.bump();907}908fn literal(p: &mut Parser) {909	assert!(Literal::can_cast(p.current()));910	p.bump();911}912fn lhs_basic(p: &mut Parser) -> Option<CompletedMarker> {913	let _e = p.expected_syntax_name("value");914	Some(if Literal::can_cast(p.current()) {915		let m = p.start();916		literal(p);917		m.complete(p, EXPR_LITERAL)918	} else if Text::can_cast(p.current()) {919		let m = p.start();920		text(p);921		m.complete(p, EXPR_STRING)922	} else if Number::can_cast(p.current()) {923		let m = p.start();924		number(p);925		m.complete(p, EXPR_NUMBER)926	} else if p.at(IDENT) {927		let m = p.start();928		name(p);929		m.complete(p, EXPR_VAR)930	} else if p.at(INTRINSIC_THIS_FILE) {931		let m = p.start();932		p.bump();933		m.complete(p, EXPR_INTRINSIC_THIS_FILE)934	} else if p.at(INTRINSIC_ID) {935		let m = p.start();936		p.bump();937		m.complete(p, EXPR_INTRINSIC_ID)938	} else if p.at(INTRINSIC) {939		let m = p.start();940		p.bump();941		p.expect(T!['(']);942		name(p);943		p.expect(T![')']);944		m.complete(p, EXPR_INTRINSIC)945	} else if p.at(T![if]) {946		let m = p.start();947		p.bump();948		expr(p);949		p.expect(T![then]);950		expr(p).map(|c| c.wrap(p, TRUE_EXPR));951		if p.at(T![else]) {952			p.bump();953			expr(p).map(|c| c.wrap(p, FALSE_EXPR));954		}955		m.complete(p, EXPR_IF_THEN_ELSE)956	} else if p.at(T!['[']) {957		array(p)958	} else if p.at(T!['{']) {959		object(p)960	} else if p.at(T![local]) {961		let m = p.start();962		p.bump();963		loop {964			if p.at(T![;]) {965				p.bump();966				break;967			}968			bind(p);969970			if p.at(T![,]) {971				p.bump();972				continue;973			}974			p.expect(T![;]);975			break;976		}977		expr(p);978		m.complete(p, EXPR_LOCAL)979	} else if p.at(T![function]) {980		let m = p.start();981		p.bump();982		params_desc(p);983		expr(p);984		m.complete(p, EXPR_FUNCTION)985	} else if p.at(T![error]) {986		let m = p.start();987		p.bump();988		expr(p);989		m.complete(p, EXPR_ERROR)990	} else if p.at(T![assert]) {991		let m = p.start();992		assertion(p);993		p.expect(T![;]);994		expr(p);995		m.complete(p, EXPR_ASSERT)996	} else if p.at(T![import]) || p.at(T![importstr]) || p.at(T![importbin]) {997		let m = p.start();998		p.bump();999		text(p);1000		m.complete(p, EXPR_IMPORT)1001	} else if p.at(T![-]) || p.at(T![!]) || p.at(T![~]) {1002		let op = match p.current() {1003			T![-] => UnaryOperator::Minus,1004			T![!] => UnaryOperator::Not,1005			T![~] => UnaryOperator::BitNegate,1006			_ => unreachable!(),1007		};1008		let ((), right_binding_power) = op.binding_power();10091010		let m = p.start();1011		p.bump();1012		expr_binding_power(p, right_binding_power);1013		m.complete(p, EXPR_UNARY)1014	} else if p.at(T!['(']) {1015		let m = p.start();1016		p.bump();1017		expr(p);1018		p.expect(T![')']);1019		m.complete(p, EXPR_PARENED)1020	} else {1021		p.error_with_recovery_set(TS![]);1022		return None;1023	})1024}10251026impl Parse {1027	pub fn syntax(&self) -> SyntaxNode {1028		SyntaxNode::new_root(self.green_node.clone())1029	}1030}
after · crates/jrsonnet-rowan-parser/src/parser.rs
1use std::{cell::Cell, fmt::Display, rc::Rc};23use miette::{LabeledSpan, SourceOffset, SourceSpan};4use rowan::{GreenNode, TextRange, TextSize};56use crate::{7	event::Event,8	lex::Lexeme,9	marker::{AsRange, CompletedMarker, Marker, Ranger},10	nodes::{BinaryOperatorKind, Literal, Number, Text, Trivia, UnaryOperatorKind},11	token_set::SyntaxKindSet,12	AstToken, SyntaxKind,13	SyntaxKind::*,14	SyntaxNode, T, TS,15};1617pub struct Parse {18	pub green_node: GreenNode,19	pub errors: Vec<SyntaxError>,20}2122#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]23pub enum ExpectedSyntax {24	Named(&'static str),25	Unnamed(SyntaxKind),26}27impl Display for ExpectedSyntax {28	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {29		match self {30			ExpectedSyntax::Named(n) => write!(f, "{}", n),31			ExpectedSyntax::Unnamed(u) => write!(f, "{:?}", u),32		}33	}34}3536pub struct Parser<'i> {37	// TODO: remove all trivia before feeding to parser?38	lexemes: &'i [Lexeme<'i>],39	pub offset: usize,40	pub events: Vec<Event>,41	pub entered: u32,42	pub hints: Vec<(u32, TextRange, String)>,43	pub last_error_token: usize,44	expected_syntax: Option<ExpectedSyntax>,45	expected_syntax_tracking_state: Rc<Cell<ExpectedSyntaxTrackingState>>,46	steps: Cell<u64>,47}4849const DEFAULT_RECOVERY_SET: SyntaxKindSet = TS![];5051#[derive(Clone, Debug, PartialEq, Eq)]52pub enum SyntaxError {53	Unexpected {54		expected: ExpectedSyntax,55		found: SyntaxKind,56		range: TextRange,57	},58	Missing {59		expected: ExpectedSyntax,60		offset: TextSize,61	},62	Custom {63		error: String,64		range: TextRange,65	},66	Hint {67		error: String,68		range: TextRange,69	},70}7172impl From<SyntaxError> for LabeledSpan {73	fn from(val: SyntaxError) -> Self {74		match val {75			SyntaxError::Unexpected {76				expected,77				found,78				range,79			} => LabeledSpan::new_with_span(80				Some(format!("expected {}, found {:?}", expected, found)),81				SourceSpan::new(82					SourceOffset::from(usize::from(range.start())),83					SourceOffset::from(usize::from(range.end() - range.start())),84				),85			),86			SyntaxError::Missing { expected, offset } => LabeledSpan::new_with_span(87				Some(format!("missing {}", expected)),88				SourceSpan::new(89					SourceOffset::from(usize::from(offset)),90					SourceOffset::from(0),91				),92			),93			SyntaxError::Custom { error, range } | SyntaxError::Hint { error, range } => {94				LabeledSpan::new_with_span(95					Some(error),96					SourceSpan::new(97						SourceOffset::from(usize::from(range.start())),98						SourceOffset::from(usize::from(range.end() - range.start())),99					),100				)101			}102		}103	}104}105106impl<'i> Parser<'i> {107	pub fn new(lexemes: &'i [Lexeme<'i>]) -> Self {108		Self {109			lexemes,110			offset: 0,111			events: vec![],112			entered: 0,113			last_error_token: 0,114			hints: vec![],115			expected_syntax: None,116			expected_syntax_tracking_state: Rc::new(Cell::new(117				ExpectedSyntaxTrackingState::Unnamed,118			)),119			steps: Cell::new(0),120		}121	}122	pub fn clear_outdated_hints(&mut self) {123		let amount = self124			.hints125			.iter()126			.rev()127			.take_while(|h| h.0 > self.entered)128			.count();129		self.hints.truncate(self.hints.len() - amount)130	}131	fn clear_expected_syntaxes(&mut self) {132		self.expected_syntax = None;133		self.expected_syntax_tracking_state134			.set(ExpectedSyntaxTrackingState::Unnamed);135	}136	pub fn start(&mut self) -> Marker {137		self.skip_trivia();138		let start_event_idx = self.events.len();139		self.events.push(Event::Pending);140		self.entered += 1;141		Marker::new(start_event_idx)142	}143	pub fn start_ranger(&mut self) -> Ranger {144		self.skip_trivia();145		let pos = self.offset;146		Ranger { pos }147	}148	pub fn parse(mut self) -> Vec<Event> {149		let m = self.start();150		expr(&mut self);151		self.expect(EOF);152		m.complete(&mut self, SOURCE_FILE);153154		self.events155	}156157	pub(crate) fn expect(&mut self, kind: SyntaxKind) {158		self.expect_with_recovery_set(kind, TS![])159	}160161	pub(crate) fn expect_with_recovery_set(162		&mut self,163		kind: SyntaxKind,164		recovery_set: SyntaxKindSet,165	) {166		if self.at(kind) {167			if kind != EOF {168				self.bump();169			}170		} else {171			self.error_with_recovery_set(recovery_set);172		}173	}174175	pub(crate) fn expect_with_no_skip(&mut self, kind: SyntaxKind) {176		if self.at(kind) {177			self.bump();178		} else {179			self.error_with_no_skip();180		}181	}182	fn current_token(&self) -> Lexeme<'i> {183		self.lexemes[self.offset]184	}185	fn previous_token(&mut self) -> Option<Lexeme<'i>> {186		if self.offset == 0 {187			return None;188		}189		let mut previous_token_idx = self.offset - 1;190		while self191			.lexemes192			.get(previous_token_idx)193			.map_or(false, |l| Trivia::can_cast(l.kind))194			&& previous_token_idx != 0195		{196			previous_token_idx -= 1;197		}198199		Some(self.lexemes[previous_token_idx])200	}201	pub fn start_of_token(&self, mut idx: usize) -> TextSize {202		while Trivia::can_cast(self.lexemes[idx].kind) {203			idx += 1;204		}205		self.lexemes[idx].range.start()206	}207	pub fn end_of_token(&self, mut idx: usize) -> TextSize {208		while Trivia::can_cast(self.lexemes[idx].kind) {209			idx -= 1;210		}211		self.lexemes[idx].range.end()212	}213	pub(crate) fn custom_error(&mut self, marker: impl AsRange, error: impl AsRef<str>) {214		self.last_error_token = marker.end_token();215		self.events.push(Event::Error(SyntaxError::Custom {216			error: error.as_ref().to_string(),217			range: marker.as_range(self),218		}));219	}220	pub(crate) fn error_with_recovery_set(221		&mut self,222		recovery_set: SyntaxKindSet,223	) -> Option<CompletedMarker> {224		self.error_with_recovery_set_no_default(recovery_set.union(DEFAULT_RECOVERY_SET))225	}226	pub fn error_with_no_skip(&mut self) -> Option<CompletedMarker> {227		self.error_with_recovery_set_no_default(SyntaxKindSet::ALL)228	}229230	pub fn error_with_recovery_set_no_default(231		&mut self,232		recovery_set: SyntaxKindSet,233	) -> Option<CompletedMarker> {234		let expected_syntax = self235			.expected_syntax236			.take()237			.unwrap_or(ExpectedSyntax::Named("unknown"));238		self.expected_syntax_tracking_state239			.set(ExpectedSyntaxTrackingState::Unnamed);240241		self.skip_trivia();242		if self.at_end() || self.at_ts(recovery_set) {243			let range = self244				.previous_token()245				.map(|t| t.range)246				.unwrap_or_else(|| TextRange::at(TextSize::from(0), TextSize::from(0)));247248			self.events.push(Event::Error(SyntaxError::Missing {249				expected: expected_syntax,250				offset: range.end(),251			}));252			return None;253		}254255		let current_token = self.current_token();256257		self.events.push(Event::Error(SyntaxError::Unexpected {258			expected: expected_syntax,259			found: current_token.kind,260			range: current_token.range,261		}));262		self.clear_expected_syntaxes();263		self.last_error_token = self.offset;264265		let m = self.start();266		self.bump();267		Some(m.complete(self, SyntaxKind::ERROR))268	}269	fn bump_assert(&mut self, kind: SyntaxKind) {270		self.skip_trivia();271		assert!(self.at(kind), "expected {:?}", kind);272		self.bump_remap(self.current());273	}274	fn bump(&mut self) {275		self.skip_trivia();276		self.bump_remap(self.current());277	}278	fn bump_remap(&mut self, kind: SyntaxKind) {279		self.skip_trivia();280		assert_ne!(self.offset, self.lexemes.len(), "already at end");281		self.events.push(Event::Token { kind });282		self.offset += 1;283		self.clear_expected_syntaxes();284	}285	fn step(&self) {286		use std::fmt::Write;287		let steps = self.steps.get();288		if steps >= 15000000 {289			let mut out = "seems like parsing is stuck".to_owned();290			{291				let last = 20;292				write!(out, "\n\nLast {} events:", last).unwrap();293				for (i, event) in self294					.events295					.iter()296					.skip(self.events.len().saturating_sub(last))297					.enumerate()298				{299					write!(out, "\n{i}. {event:?}").unwrap();300				}301			}302			{303				let next = 20;304				write!(out, "\n\nNext {next} tokens:").unwrap();305				for (i, tok) in self.lexemes.iter().skip(self.offset).take(next).enumerate() {306					write!(out, "\n{i}. {tok:?}").unwrap();307				}308			}309			panic!("{out}")310		}311		self.steps.set(steps + 1);312	}313	fn nth(&self, i: usize) -> SyntaxKind {314		self.step();315		let mut offset = self.offset;316		for _ in 0..i {317			while self318				.lexemes319				.get(offset)320				.map(|l| Trivia::can_cast(l.kind))321				.unwrap_or(false)322			{323				offset += 1;324			}325			offset += 1;326		}327		while self328			.lexemes329			.get(offset)330			.map(|l| Trivia::can_cast(l.kind))331			.unwrap_or(false)332		{333			offset += 1;334		}335		self.lexemes.get(offset).map(|l| l.kind).unwrap_or(EOF)336	}337	fn current(&self) -> SyntaxKind {338		self.nth(0)339	}340	fn skip_trivia(&mut self) {341		while Trivia::can_cast(self.peek_raw()) {342			self.offset += 1;343		}344	}345	fn peek_raw(&mut self) -> SyntaxKind {346		self.lexemes347			.get(self.offset)348			.map(|l| l.kind)349			.unwrap_or(SyntaxKind::EOF)350	}351	#[must_use]352	pub(crate) fn expected_syntax_name(&mut self, name: &'static str) -> ExpectedSyntaxGuard {353		self.expected_syntax_tracking_state354			.set(ExpectedSyntaxTrackingState::Named);355		self.expected_syntax = Some(ExpectedSyntax::Named(name));356357		ExpectedSyntaxGuard::new(Rc::clone(&self.expected_syntax_tracking_state))358	}359	pub fn at(&mut self, kind: SyntaxKind) -> bool {360		self.nth_at(0, kind)361	}362	pub fn nth_at(&mut self, n: usize, kind: SyntaxKind) -> bool {363		if let ExpectedSyntaxTrackingState::Unnamed = self.expected_syntax_tracking_state.get() {364			self.expected_syntax = Some(ExpectedSyntax::Unnamed(kind));365		}366		self.nth(n) == kind367	}368	pub fn at_ts(&mut self, set: SyntaxKindSet) -> bool {369		set.contains(self.current())370	}371	pub fn at_end(&mut self) -> bool {372		self.at(EOF)373	}374}375pub(crate) struct ExpectedSyntaxGuard {376	expected_syntax_tracking_state: Rc<Cell<ExpectedSyntaxTrackingState>>,377}378379impl ExpectedSyntaxGuard {380	fn new(expected_syntax_tracking_state: Rc<Cell<ExpectedSyntaxTrackingState>>) -> Self {381		Self {382			expected_syntax_tracking_state,383		}384	}385}386387impl Drop for ExpectedSyntaxGuard {388	fn drop(&mut self) {389		self.expected_syntax_tracking_state390			.set(ExpectedSyntaxTrackingState::Unnamed);391	}392}393394#[derive(Debug, Clone, Copy)]395enum ExpectedSyntaxTrackingState {396	Named,397	Unnamed,398}399400fn expr(p: &mut Parser) -> Option<CompletedMarker> {401	expr_binding_power(p, 0)402}403fn expr_binding_power(p: &mut Parser, minimum_binding_power: u8) -> Option<CompletedMarker> {404	let mut lhs = lhs(p)?;405406	while let Some(op) = BinaryOperatorKind::cast(p.current())407		.or_else(|| p.at(T!['{']).then(|| BinaryOperatorKind::MetaObjectApply))408	{409		let (left_binding_power, right_binding_power) = op.binding_power();410		if left_binding_power < minimum_binding_power {411			break;412		}413414		// Object apply is not a real operator, we dont have something to bump415		if op != BinaryOperatorKind::MetaObjectApply {416			p.bump();417		}418419		let m = lhs.wrap(p, LHS_EXPR).precede(p);420		let parsed_rhs = expr_binding_power(p, right_binding_power).is_some();421		lhs = m.complete(422			p,423			if op == BinaryOperatorKind::MetaObjectApply {424				EXPR_OBJ_EXTEND425			} else {426				EXPR_BINARY427			},428		);429430		if !parsed_rhs {431			break;432		}433	}434	Some(lhs)435}436fn compspec(p: &mut Parser) {437	assert!(p.at(T![for]) || p.at(T![if]));438	if p.at(T![for]) {439		let m = p.start();440		p.bump();441		name(p);442		p.expect(T![in]);443		expr(p);444		m.complete(p, FOR_SPEC);445	} else if p.at(T![if]) {446		let m = p.start();447		p.bump();448		expr(p);449		m.complete(p, IF_SPEC);450	} else {451		unreachable!()452	}453}454fn comma(p: &mut Parser) -> bool {455	if p.at(T![,]) {456		p.bump();457		true458	} else {459		false460	}461}462fn comma_with_alternatives(p: &mut Parser, set: SyntaxKindSet) -> bool {463	if p.at(T![,]) {464		p.bump();465		true466	} else if p.at_ts(set) {467		p.expect_with_no_skip(T![,]);468		p.bump();469		true470	} else {471		false472	}473}474fn field_name(p: &mut Parser) {475	let _e = p.expected_syntax_name("field name");476	let m = p.start();477	if p.at(T!['[']) {478		p.bump();479		expr(p);480		p.expect(T![']']);481		m.complete(p, FIELD_NAME_DYNAMIC);482	} else if p.at(IDENT) {483		name(p);484		m.complete(p, FIELD_NAME_FIXED);485	} else if Text::can_cast(p.current()) {486		text(p);487		m.complete(p, FIELD_NAME_FIXED);488	} else {489		p.error_with_recovery_set(TS![;]);490	}491}492fn visibility(p: &mut Parser) {493	if p.at_ts(TS![: :: :::]) {494		p.bump()495	} else {496		p.error_with_recovery_set(TS![]);497	}498}499fn field(p: &mut Parser) {500	let m = p.start();501	field_name(p);502	let plus = if p.at(T![+]) {503		let r = p.start_ranger();504		p.bump();505		Some(r.finish(p))506	} else {507		None508	};509	let params = if p.at(T!['(']) {510		if let Some(plus) = plus {511			p.custom_error(plus, "can't extend with method");512		}513		params_desc(p);514		if p.at(T![+]) {515			let r = p.start_ranger();516			p.bump();517			p.custom_error(r.finish(p), "can't extend with method");518		}519		true520	} else {521		false522	};523	visibility(p);524	expr(p);525526	if params {527		m.complete(p, FIELD_METHOD)528	} else {529		m.complete(p, FIELD_NORMAL)530	};531}532fn assertion(p: &mut Parser) {533	let m = p.start();534	p.bump_assert(T![assert]);535	expr(p).map(|c| c.wrap(p, LHS_EXPR));536	if p.at(T![:]) {537		p.bump();538		expr(p);539	}540	m.complete(p, ASSERTION);541}542fn object(p: &mut Parser) -> CompletedMarker {543	let m_t = p.start();544	let m = p.start();545	p.bump_assert(T!['{']);546547	loop {548		if p.at(T!['}']) {549			p.bump();550			break;551		}552		let m = p.start();553		if p.at(T![local]) {554			obj_local(p);555			m.complete(p, MEMBER_BIND_STMT)556		} else if p.at(T![assert]) {557			assertion(p);558			m.complete(p, MEMBER_ASSERT_STMT)559		} else {560			field(p);561			while p.at(T![for]) || p.at(T![if]) {562				compspec(p)563			}564			m.complete(p, MEMBER_FIELD)565		};566		if comma_with_alternatives(p, SyntaxKindSet::new(&[T![=]])) {567			continue;568		}569		p.expect(R_BRACE);570		break;571	}572573	m.complete(p, OBJ_BODY_MEMBER_LIST);574	m_t.complete(p, EXPR_OBJECT)575}576fn param(p: &mut Parser) {577	let m = p.start();578	destruct(p);579	if p.at(T![=]) {580		p.bump();581		expr(p);582	}583	m.complete(p, PARAM);584}585fn params_desc(p: &mut Parser) -> CompletedMarker {586	let m = p.start();587	p.bump_assert(T!['(']);588589	loop {590		if p.at(T![')']) {591			p.bump();592			break;593		}594		param(p);595		if comma(p) {596			continue;597		}598		p.expect(T![')']);599		break;600	}601602	m.complete(p, PARAMS_DESC)603}604fn args_desc(p: &mut Parser) {605	let m = p.start();606	p.bump_assert(T!['(']);607608	let started_named = Cell::new(false);609610	loop {611		if p.at(T![')']) {612			break;613		}614615		let m = p.start();616		if p.at(IDENT) && p.nth_at(1, T![=]) {617			name(p);618			p.bump();619			expr(p);620			m.complete(p, ARG);621			started_named.set(true);622		} else {623			expr(p);624			m.complete(p, ARG);625		}626		if comma(p) {627			continue;628		}629		break;630	}631	p.expect(T![')']);632	if p.at(T![tailstrict]) {633		p.bump()634	}635	m.complete(p, ARGS_DESC);636}637638fn array(p: &mut Parser) -> CompletedMarker {639	// Start the list node640	let m = p.start();641	p.bump_assert(T!['[']);642643	// This vec will have at most one element in case of correct input644	let mut compspecs = Vec::with_capacity(1);645	let mut elems = 0;646647	loop {648		if p.at(T![']']) {649			p.bump();650			break;651		}652		elems += 1;653		expr(p);654		let c = p.start_ranger();655		let mut had_spec = false;656		while p.at(T![for]) || p.at(T![if]) {657			had_spec = true;658			compspec(p)659		}660		if had_spec {661			compspecs.push(c.finish(p));662		}663		if comma(p) {664			continue;665		}666		p.expect(T![']']);667		break;668	}669670	if elems > 1 && !compspecs.is_empty() {671		for spec in compspecs {672			p.custom_error(673				spec,674				"compspec may only be used if there is only one array element",675			)676		}677678		m.complete(p, EXPR_ARRAY)679	} else if !compspecs.is_empty() {680		m.complete(p, EXPR_ARRAY_COMP)681	} else {682		m.complete(p, EXPR_ARRAY)683	}684}685/// Returns true if it was slice, false if just index686#[must_use]687fn slice_desc_or_index(p: &mut Parser) -> bool {688	let m = p.start();689	p.bump();690	// TODO: do not treat :, ::, ::: as full tokens?691	// Start692	if !p.at(T![:]) && !p.at(T![::]) {693		expr(p);694	}695	if p.at(T![:]) {696		p.bump();697		// End698		if !p.at(T![']']) {699			expr(p).map(|c| c.wrap(p, SLICE_DESC_END));700		}701		if p.at(T![:]) {702			p.bump();703			// Step704			if !p.at(T![']']) {705				expr(p).map(|c| c.wrap(p, SLICE_DESC_STEP));706			}707		}708	} else if p.at(T![::]) {709		p.bump();710		// End711		if !p.at(T![']']) {712			expr(p).map(|c| c.wrap(p, SLICE_DESC_END));713		}714	} else {715		// It was not a slice716		p.expect(T![']']);717		m.forget(p);718		return false;719	}720	p.expect(T![']']);721	m.complete(p, SLICE_DESC);722	true723}724fn lhs(p: &mut Parser) -> Option<CompletedMarker> {725	let mut lhs = lhs_basic(p)?;726727	loop {728		if p.at(T![.]) {729			let m = lhs.precede(p);730			p.bump();731			name(p);732			lhs = m.complete(p, EXPR_INDEX);733		} else if p.at(T!['[']) {734			if slice_desc_or_index(p) {735				lhs = lhs.precede(p).complete(p, EXPR_SLICE);736			} else {737				lhs = lhs738					.wrap(p, LHS_EXPR)739					.precede(p)740					.complete(p, EXPR_INDEX_EXPR);741			}742		} else if p.at(T!['(']) {743			let m = lhs.precede(p);744			args_desc(p);745			lhs = m.complete(p, EXPR_APPLY);746		} else {747			break;748		}749	}750751	Some(lhs)752}753fn name(p: &mut Parser) {754	let m = p.start();755	p.expect(IDENT);756	m.complete(p, NAME);757}758fn destruct_rest(p: &mut Parser) {759	let m = p.start();760	p.bump_assert(T![...]);761	if p.at(IDENT) {762		p.bump()763	}764	m.complete(p, DESTRUCT_REST);765}766fn destruct_object_field(p: &mut Parser) {767	let m = p.start();768	name(p);769	if p.at(T![:]) {770		p.bump();771		destruct(p);772	};773	if p.at(T![=]) {774		p.bump();775		expr(p);776	}777	m.complete(p, DESTRUCT_OBJECT_FIELD);778}779fn obj_local(p: &mut Parser) {780	let m = p.start();781	p.bump_assert(T![local]);782	bind(p);783	m.complete(p, OBJ_LOCAL);784}785fn destruct(p: &mut Parser) -> CompletedMarker {786	let m = p.start();787	if p.at(T![?]) {788		p.bump();789		m.complete(p, DESTRUCT_SKIP)790	} else if p.at(T!['[']) {791		p.bump();792		let mut had_rest = false;793		loop {794			if p.at(T![']']) {795				p.bump();796				break;797			} else if p.at(T![...]) {798				let m_err = p.start_ranger();799				destruct_rest(p);800				if had_rest {801					p.custom_error(m_err.finish(p), "only one rest can be present in array");802				}803				had_rest = true;804			} else {805				destruct(p);806			}807			if p.at(T![,]) {808				p.bump();809				continue;810			}811			p.expect(T![']']);812			break;813		}814		m.complete(p, DESTRUCT_ARRAY)815	} else if p.at(T!['{']) {816		p.bump();817		let mut had_rest = false;818		loop {819			if p.at(T!['}']) {820				p.bump();821				break;822			} else if p.at(T![...]) {823				let m_err = p.start_ranger();824				destruct_rest(p);825				if had_rest {826					p.custom_error(m_err.finish(p), "only one rest can be present in object");827				}828				had_rest = true;829			} else {830				if had_rest {831					p.error_with_recovery_set(TS![]);832				}833				destruct_object_field(p);834			}835			if p.at(T![,]) {836				p.bump();837				continue;838			}839			p.expect(T!['}']);840			break;841		}842		m.complete(p, DESTRUCT_OBJECT)843	} else if p.at(IDENT) {844		name(p);845		m.complete(p, DESTRUCT_FULL)846	} else {847		m.complete(p, ERROR)848	}849}850fn bind(p: &mut Parser) {851	let m = p.start();852	if p.at(IDENT) && p.nth_at(1, T!['(']) {853		name(p);854		params_desc(p);855		p.expect(T![=]);856		expr(p);857		m.complete(p, BIND_FUNCTION)858	} else {859		destruct(p);860		p.expect(T![=]);861		expr(p);862		m.complete(p, BIND_DESTRUCT)863	};864}865fn text(p: &mut Parser) {866	assert!(Text::can_cast(p.current()));867	p.bump();868}869fn number(p: &mut Parser) {870	assert!(Number::can_cast(p.current()));871	p.bump();872}873fn literal(p: &mut Parser) {874	assert!(Literal::can_cast(p.current()));875	p.bump();876}877fn lhs_basic(p: &mut Parser) -> Option<CompletedMarker> {878	let _e = p.expected_syntax_name("value");879	Some(if Literal::can_cast(p.current()) {880		let m = p.start();881		literal(p);882		m.complete(p, EXPR_LITERAL)883	} else if Text::can_cast(p.current()) {884		let m = p.start();885		text(p);886		m.complete(p, EXPR_STRING)887	} else if Number::can_cast(p.current()) {888		let m = p.start();889		number(p);890		m.complete(p, EXPR_NUMBER)891	} else if p.at(IDENT) {892		let m = p.start();893		name(p);894		m.complete(p, EXPR_VAR)895	} else if p.at(INTRINSIC_THIS_FILE) {896		let m = p.start();897		p.bump();898		m.complete(p, EXPR_INTRINSIC_THIS_FILE)899	} else if p.at(INTRINSIC_ID) {900		let m = p.start();901		p.bump();902		m.complete(p, EXPR_INTRINSIC_ID)903	} else if p.at(INTRINSIC) {904		let m = p.start();905		p.bump();906		p.expect(T!['(']);907		name(p);908		p.expect(T![')']);909		m.complete(p, EXPR_INTRINSIC)910	} else if p.at(T![if]) {911		let m = p.start();912		p.bump();913		expr(p);914		p.expect(T![then]);915		expr(p).map(|c| c.wrap(p, TRUE_EXPR));916		if p.at(T![else]) {917			p.bump();918			expr(p).map(|c| c.wrap(p, FALSE_EXPR));919		}920		m.complete(p, EXPR_IF_THEN_ELSE)921	} else if p.at(T!['[']) {922		array(p)923	} else if p.at(T!['{']) {924		object(p)925	} else if p.at(T![local]) {926		let m = p.start();927		p.bump();928		loop {929			if p.at(T![;]) {930				p.bump();931				break;932			}933			bind(p);934935			if p.at(T![,]) {936				p.bump();937				continue;938			}939			p.expect(T![;]);940			break;941		}942		expr(p);943		m.complete(p, EXPR_LOCAL)944	} else if p.at(T![function]) {945		let m = p.start();946		p.bump();947		params_desc(p);948		expr(p);949		m.complete(p, EXPR_FUNCTION)950	} else if p.at(T![error]) {951		let m = p.start();952		p.bump();953		expr(p);954		m.complete(p, EXPR_ERROR)955	} else if p.at(T![assert]) {956		let m = p.start();957		assertion(p);958		p.expect(T![;]);959		expr(p);960		m.complete(p, EXPR_ASSERT)961	} else if p.at(T![import]) || p.at(T![importstr]) || p.at(T![importbin]) {962		let m = p.start();963		p.bump();964		text(p);965		m.complete(p, EXPR_IMPORT)966	} else if let Some(op) = UnaryOperatorKind::cast(p.current()) {967		let ((), right_binding_power) = op.binding_power();968969		let m = p.start();970		p.bump();971		expr_binding_power(p, right_binding_power);972		m.complete(p, EXPR_UNARY)973	} else if p.at(T!['(']) {974		let m = p.start();975		p.bump();976		expr(p);977		p.expect(T![')']);978		m.complete(p, EXPR_PARENED)979	} else {980		p.error_with_recovery_set(TS![]);981		return None;982	})983}984985impl Parse {986	pub fn syntax(&self) -> SyntaxNode {987		SyntaxNode::new_root(self.green_node.clone())988	}989}
addedcrates/jrsonnet-rowan-parser/src/precedence.rsdiffbeforeafterboth
--- /dev/null
+++ b/crates/jrsonnet-rowan-parser/src/precedence.rs
@@ -0,0 +1,30 @@
+use crate::nodes::{BinaryOperatorKind, UnaryOperatorKind};
+
+impl BinaryOperatorKind {
+	pub fn binding_power(&self) -> (u8, u8) {
+		match self {
+			Self::MetaObjectApply => (22, 23),
+			Self::Mul | Self::Div | Self::Modulo => (20, 21),
+			Self::Plus | Self::Minus => (18, 19),
+			Self::Lhs | Self::Rhs => (16, 17),
+			Self::Lt | Self::Gt | Self::Le | Self::Ge | Self::InKw => (14, 15),
+			Self::Eq | Self::Ne => (12, 13),
+			Self::BitAnd => (10, 11),
+			Self::BitXor => (8, 9),
+			Self::BitOr => (6, 7),
+			Self::And => (4, 5),
+			Self::Or => (2, 3),
+			Self::ErrorNoOperator => (0, 1),
+		}
+	}
+}
+
+impl UnaryOperatorKind {
+	pub fn binding_power(&self) -> ((), u8) {
+		match self {
+			Self::Minus => ((), 20),
+			Self::Not => ((), 20),
+			Self::BitNot => ((), 20),
+		}
+	}
+}
deletedcrates/jrsonnet-rowan-parser/src/unary.rsdiffbeforeafterboth
--- a/crates/jrsonnet-rowan-parser/src/unary.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
-pub enum UnaryOperator {
-	Minus,
-	Not,
-	BitNegate,
-}
-impl UnaryOperator {
-	pub fn binding_power(&self) -> ((), u8) {
-		match self {
-			UnaryOperator::Minus => ((), 20),
-			UnaryOperator::Not => ((), 20),
-			UnaryOperator::BitNegate => ((), 20),
-		}
-	}
-}
modifiedxtask/src/sourcegen/mod.rsdiffbeforeafterboth
--- a/xtask/src/sourcegen/mod.rs
+++ b/xtask/src/sourcegen/mod.rs
@@ -353,22 +353,30 @@
 			let ast_node = quote! {
 				impl AstToken for #name {
 					fn can_cast(kind: SyntaxKind) -> bool {
+						#kind_name::can_cast(kind)
+					}
+					fn cast(syntax: SyntaxToken) -> Option<Self> {
+						let kind = #kind_name::cast(syntax.kind())?;
+						Some(#name { syntax, kind })
+					}
+					fn syntax(&self) -> &SyntaxToken {
+						&self.syntax
+					}
+				}
+
+				impl #kind_name {
+					fn can_cast(kind: SyntaxKind) -> bool {
 						match kind {
 							#(#kinds)|* => true,
 							_ => false,
 						}
 					}
-					fn cast(syntax: SyntaxToken) -> Option<Self> {
-						let res = match syntax.kind() {
-							#(
-							#kinds => #name { syntax, kind: #kind_name::#variants },
-							)*
+					pub fn cast(kind: SyntaxKind) -> Option<Self> {
+						let res = match kind {
+							#(#kinds => Self::#variants,)*
 							_ => return None,
 						};
 						Some(res)
-					}
-					fn syntax(&self) -> &SyntaxToken {
-						&self.syntax
 					}
 				}
 			};