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 15 Pending,16 17 Start {18 kind: SyntaxKind,19 20 21 forward_parent: Option<usize>,22 },23 24 Token {25 kind: SyntaxKind,26 },27 28 VirtualToken {29 kind: SyntaxKind,30 },31 32 Finish {33 34 wrapper: Option<usize>,35 },36 Error(SyntaxError),37 38 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 94 95 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}