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

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	lex::Lexeme,7	nodes::Trivia,8	parser::{LocatedSyntaxError, Parse, SyntaxError},9	AstToken, JsonnetLanguage, SyntaxKind,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		if let Some(lex) = self.lexemes.get(self.offset) {61			lex.range.start()62		} else if let Some(lex) = self.lexemes.get(self.offset - 1) {63			lex.range.end()64		} else {65			panic!("hard oob")66		}67	}6869	pub(super) fn finish(mut self) -> Parse {70		let mut eat_start_whitespace = false;71		let mut depth = 0;72		let mut error_starts_at = Vec::new();73		for idx in 0..self.events.len() {74			match mem::replace(&mut self.events[idx], Event::Noop) {75				Event::Start {76					kind,77					forward_parent,78				} => {79					if depth != 0 {80						self.skip_whitespace();81					}82					let mut kinds = vec![kind];8384					let mut idx = idx;85					let mut forward_parent = forward_parent;8687					// Walk through the forward parent of the forward parent, and the forward parent88					// of that, and of that, etc. until we reach a StartNode event without a forward89					// parent.90					while let Some(fp) = forward_parent {91						idx += fp.get();9293						forward_parent = if let Event::Start {94							kind,95							forward_parent,96						} = mem::replace(&mut self.events[idx], Event::Noop)97						{98							kinds.push(kind);99							forward_parent100						} else {101							unreachable!()102						};103					}104105					for kind in kinds.into_iter().rev() {106						self.builder.start_node(JsonnetLanguage::kind_to_raw(kind));107						depth += 1;108						if depth == 1 {109							self.skip_whitespace();110						}111						error_starts_at.push(self.text_offset());112					}113114					eat_start_whitespace = false;115				}116				Event::Token { kind } => {117					if eat_start_whitespace {118						self.skip_whitespace();119					}120					self.token(kind);121					eat_start_whitespace = true;122				}123				// Event::VirtualToken { kind } => {124				// 	if eat_start_whitespace {125				// 		self.skip_whitespace();126				// 	}127				// 	self.virtual_token(kind);128				// 	eat_start_whitespace = false;129				// }130				Event::Finish { wrapper, error } => {131					if depth == 1 {132						self.skip_whitespace();133					}134					let range = (135						error_starts_at.pop().expect("starts == finishes"),136						self.text_offset(),137					);138					if let Some(error) = error {139						self.errors.push(LocatedSyntaxError {140							error: *error,141							range: TextRange::new(range.0, range.1),142						})143					}144					self.builder.finish_node();145					depth -= 1;146					let mut idx = idx;147					let mut wrapper = wrapper;148					while let Some(w) = wrapper {149						idx += w.get();150						wrapper = if let Event::Finish { wrapper, error } =151							mem::replace(&mut self.events[idx], Event::Noop)152						{153							let range = (154								error_starts_at.pop().expect("starts == finishes"),155								self.text_offset(),156							);157							if let Some(error) = error {158								self.errors.push(LocatedSyntaxError {159									error: *error,160									range: TextRange::new(range.0, range.1),161								})162							}163164							if depth == 1 {165								self.skip_whitespace();166							}167							self.builder.finish_node();168							depth -= 1;169							wrapper170						} else {171							unreachable!()172						}173					}174					eat_start_whitespace = true;175				}176				Event::Pending => panic!("pending event should not appear in finished events"),177				Event::Noop => {}178			}179		}180181		Parse {182			green_node: self.builder.finish(),183			errors: self.errors,184		}185	}186	// fn virtual_token(&mut self, kind: SyntaxKind) {187	// 	self.builder.token(JsonnetLanguage::kind_to_raw(kind), "")188	// }189	fn token(&mut self, kind: SyntaxKind) {190		let lexeme = self.lexemes[self.offset];191		self.builder192			.token(JsonnetLanguage::kind_to_raw(kind), lexeme.text);193		self.offset += 1;194	}195	fn skip_whitespace(&mut self) {196		while let Some(lexeme) = self.lexemes.get(self.offset) {197			if !Trivia::can_cast(lexeme.kind) {198				break;199			}200201			self.token(lexeme.kind);202		}203	}204}