git.delta.rocks / jrsonnet / refs/commits / 6beafa85136f

difftreelog

source

crates/jrsonnet-rowan-parser/src/event.rs5.0 KiBsourcehistory
1use std::mem;23use rowan::{GreenNodeBuilder, Language, TextRange, TextSize};45use crate::{6	lex::Lexeme,7	nodes::Trivia,8	parser::{LocatedSyntaxError, Parse, SyntaxError},9	AstToken, JsonnetLanguage, SyntaxKind,10};1112#[derive(Clone, Debug, PartialEq, Eq)]13pub enum Event {14	/// Used for unfinished markers15	Pending,16	/// After marker is completed, Pending event is replaced with Start17	Start {18		kind: SyntaxKind,19		/// If marker is preceded or wrapped - instead of reordering events, we20		/// insert start event in the end of events Vec instead, and store relative offset to this event here21		forward_parent: Option<usize>,22	},23	/// Eat token24	Token {25		kind: SyntaxKind,26	},27	/// Push token, but do not eat anything,28	VirtualToken {29		kind: SyntaxKind,30	},31	/// Position of finished node32	Finish {33		/// Same as forward_parent of Start, but for wrapping34		wrapper: Option<usize>,35	},36	Error(SyntaxError),37	/// Used for dropped markers and other things38	Noop,39}4041pub(super) struct Sink<'i> {42	pub builder: GreenNodeBuilder<'static>,43	lexemes: &'i [Lexeme<'i>],44	offset: usize,45	events: Vec<Event>,46	pub errors: Vec<LocatedSyntaxError>,47}4849impl<'i> Sink<'i> {50	pub(super) fn new(events: Vec<Event>, lexemes: &'i [Lexeme<'i>]) -> Self {51		Self {52			builder: GreenNodeBuilder::new(),53			lexemes,54			offset: 0,55			events,56			errors: vec![],57		}58	}5960	fn text_offset(&self) -> TextSize {61		if self.offset == 0 {62			return 0.into();63		};64		if let Some(lex) = self.lexemes.get(self.offset) {65			lex.range.start()66		} else if let Some(lex) = self.lexemes.get(self.offset - 1) {67			lex.range.end()68		} else {69			panic!("hard oob")70		}71	}7273	pub(super) fn finish(mut self) -> Parse {74		let mut eat_start_whitespace = false;75		let mut depth = 0;76		let mut error_starts_at = Vec::new();77		let mut error_last_range = None;78		for idx in 0..self.events.len() {79			match mem::replace(&mut self.events[idx], Event::Noop) {80				Event::Start {81					kind,82					forward_parent,83				} => {84					if depth != 0 {85						self.skip_whitespace();86					}87					error_last_range = None;88					let mut kinds = vec![kind];8990					let mut idx = idx;91					let mut forward_parent = forward_parent;9293					// Walk through the forward parent of the forward parent, and the forward parent94					// of that, and of that, etc. until we reach a StartNode event without a forward95					// parent.96					while let Some(fp) = forward_parent {97						idx += fp;9899						forward_parent = if let Event::Start {100							kind,101							forward_parent,102						} = mem::replace(&mut self.events[idx], Event::Noop)103						{104							kinds.push(kind);105							forward_parent106						} else {107							unreachable!()108						};109					}110111					for kind in kinds.into_iter().rev() {112						self.builder.start_node(JsonnetLanguage::kind_to_raw(kind));113						depth += 1;114						if depth == 1 {115							self.skip_whitespace();116						}117						error_starts_at.push(self.text_offset());118					}119120					eat_start_whitespace = false;121				}122				Event::Token { kind } => {123					if eat_start_whitespace {124						self.skip_whitespace();125					}126					error_last_range = None;127					self.token(kind);128					eat_start_whitespace = true;129				}130				Event::VirtualToken { kind } => {131					if eat_start_whitespace {132						self.skip_whitespace();133					}134					error_last_range = None;135					self.virtual_token(kind);136					eat_start_whitespace = false;137				}138				Event::Finish { wrapper } => {139					if depth == 1 {140						self.skip_whitespace();141					}142					error_last_range = Some((143						error_starts_at.pop().expect("starts == finishes"),144						self.text_offset(),145					));146					self.builder.finish_node();147					depth -= 1;148					let mut idx = idx;149					let mut wrapper = wrapper;150					while let Some(w) = wrapper {151						idx += w;152						wrapper = if let Event::Finish { wrapper } =153							mem::replace(&mut self.events[idx], Event::Noop)154						{155							error_last_range = Some((156								error_starts_at.pop().expect("starts == finishes"),157								self.text_offset(),158							));159							if depth == 1 {160								self.skip_whitespace();161							}162							self.builder.finish_node();163							depth -= 1;164							wrapper165						} else {166							unreachable!()167						}168					}169					eat_start_whitespace = true;170				}171				Event::Pending => panic!("pending event should not appear in finished events"),172				Event::Noop => {}173				Event::Error(error) => {174					let (start, end) = error_last_range175						.take()176						.expect("expected error event right after closed node");177					self.errors.push(LocatedSyntaxError {178						error,179						range: TextRange::new(start, end),180					});181				}182			}183		}184185		Parse {186			green_node: self.builder.finish(),187			errors: self.errors,188		}189	}190	fn virtual_token(&mut self, kind: SyntaxKind) {191		self.builder.token(JsonnetLanguage::kind_to_raw(kind), "")192	}193	fn token(&mut self, kind: SyntaxKind) {194		let lexeme = self.lexemes[self.offset];195		self.builder196			.token(JsonnetLanguage::kind_to_raw(kind), lexeme.text);197		self.offset += 1;198	}199	fn skip_whitespace(&mut self) {200		while let Some(lexeme) = self.lexemes.get(self.offset) {201			if !Trivia::can_cast(lexeme.kind) {202				break;203			}204205			self.token(lexeme.kind);206		}207	}208}