difftreelog
refactor deduplicate operator definitions
in: master
9 files changed
crates/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 =
crates/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),
- }
- }
-}
crates/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 {
crates/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,
crates/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;
crates/jrsonnet-rowan-parser/src/parser.rsdiffbeforeafterboth1use 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}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}crates/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),
+ }
+ }
+}
crates/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),
- }
- }
-}
xtask/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
}
}
};