git.delta.rocks / jrsonnet / refs/heads / master

difftreelog

source

crates/jrsonnet-rowan-parser/src/event.rs5.0 KiBsourcehistory
1use std::{mem, num::NonZeroUsize};23use rowan::{GreenNodeBuilder, Language, TextRange, TextSize};45use crate::{6	AstToken, JsonnetLanguage, SyntaxKind,7	lex::Lexeme,8	nodes::Trivia,9	parser::{LocatedSyntaxError, Parse, SyntaxError},10};1112#[derive(Clone, Debug)]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<NonZeroUsize>,22	},23	/// Eat token24	Token { kind: SyntaxKind },25	/// Push token, but do not eat anything,26	// VirtualToken { kind: SyntaxKind },27	/// Position of finished node28	Finish {29		/// Same as `forward_parent` of Start, but for wrapping30		wrapper: Option<NonZeroUsize>,31		error: Option<Box<SyntaxError>>,32	},33	/// Used for dropped markers and other things34	Noop,35}3637pub(super) struct Sink<'i> {38	pub builder: GreenNodeBuilder<'static>,39	lexemes: &'i [Lexeme<'i>],40	offset: usize,41	events: Vec<Event>,42	pub errors: Vec<LocatedSyntaxError>,43}4445impl<'i> Sink<'i> {46	pub(super) fn new(events: Vec<Event>, lexemes: &'i [Lexeme<'i>]) -> Self {47		Self {48			builder: GreenNodeBuilder::new(),49			lexemes,50			offset: 0,51			events,52			errors: vec![],53		}54	}5556	fn text_offset(&self) -> TextSize {57		if self.offset == 0 {58			return 0.into();59		}60		self.lexemes.get(self.offset).map_or_else(61			|| {62				self.lexemes63					.get(self.offset - 1)64					.map_or_else(|| panic!("hard oob"), |lex| lex.range.end())65			},66			|lex| lex.range.start(),67		)68	}6970	pub(super) fn finish(mut self) -> Parse {71		let mut eat_start_whitespace = false;72		let mut depth = 0;73		let mut error_starts_at = Vec::new();74		for idx in 0..self.events.len() {75			match mem::replace(&mut self.events[idx], Event::Noop) {76				Event::Start {77					kind,78					forward_parent,79				} => {80					if depth != 0 {81						self.skip_whitespace();82					}83					let mut kinds = vec![kind];8485					let mut idx = idx;86					let mut forward_parent = forward_parent;8788					// Walk through the forward parent of the forward parent, and the forward parent89					// of that, and of that, etc. until we reach a StartNode event without a forward90					// parent.91					while let Some(fp) = forward_parent {92						idx += fp.get();9394						forward_parent = if let Event::Start {95							kind,96							forward_parent,97						} = mem::replace(&mut self.events[idx], Event::Noop)98						{99							kinds.push(kind);100							forward_parent101						} else {102							unreachable!()103						};104					}105106					for kind in kinds.into_iter().rev() {107						self.builder.start_node(JsonnetLanguage::kind_to_raw(kind));108						depth += 1;109						if depth == 1 {110							self.skip_whitespace();111						}112						error_starts_at.push(self.text_offset());113					}114115					eat_start_whitespace = false;116				}117				Event::Token { kind } => {118					if eat_start_whitespace {119						self.skip_whitespace();120					}121					self.token(kind);122					eat_start_whitespace = true;123				}124				// Event::VirtualToken { kind } => {125				// 	if eat_start_whitespace {126				// 		self.skip_whitespace();127				// 	}128				// 	self.virtual_token(kind);129				// 	eat_start_whitespace = false;130				// }131				Event::Finish { wrapper, error } => {132					if depth == 1 {133						self.skip_whitespace();134					}135					let range = (136						error_starts_at.pop().expect("starts == finishes"),137						self.text_offset(),138					);139					if let Some(error) = error {140						self.errors.push(LocatedSyntaxError {141							error: *error,142							range: TextRange::new(range.0, range.1),143						});144					}145					self.builder.finish_node();146					depth -= 1;147					let mut idx = idx;148					let mut wrapper = wrapper;149					while let Some(w) = wrapper {150						idx += w.get();151						wrapper = if let Event::Finish { wrapper, error } =152							mem::replace(&mut self.events[idx], Event::Noop)153						{154							let range = (155								error_starts_at.pop().expect("starts == finishes"),156								self.text_offset(),157							);158							if let Some(error) = error {159								self.errors.push(LocatedSyntaxError {160									error: *error,161									range: TextRange::new(range.0, range.1),162								});163							}164165							if depth == 1 {166								self.skip_whitespace();167							}168							self.builder.finish_node();169							depth -= 1;170							wrapper171						} else {172							unreachable!()173						}174					}175					eat_start_whitespace = true;176				}177				Event::Pending => panic!("pending event should not appear in finished events"),178				Event::Noop => {}179			}180		}181182		Parse {183			green_node: self.builder.finish(),184			errors: self.errors,185		}186	}187	// fn virtual_token(&mut self, kind: SyntaxKind) {188	// 	self.builder.token(JsonnetLanguage::kind_to_raw(kind), "")189	// }190	fn token(&mut self, kind: SyntaxKind) {191		let lexeme = self.lexemes[self.offset];192		self.builder193			.token(JsonnetLanguage::kind_to_raw(kind), lexeme.text);194		self.offset += 1;195	}196	fn skip_whitespace(&mut self) {197		while let Some(lexeme) = self.lexemes.get(self.offset) {198			if !Trivia::can_cast(lexeme.kind) {199				break;200			}201202			self.token(lexeme.kind);203		}204	}205}