ll_sparql_parser/parser/
mod.rs1mod grammar;
2
3use std::{cell::Cell, ops::Range};
4
5use crate::SyntaxKind;
6use grammar::{parse_QueryUnit, parse_UpdateUnit};
7use logos::Logos;
8use rowan::{GreenNode, GreenNodeBuilder, TextRange, TextSize};
9
10pub struct Parser {
11 tokens: Vec<Token>,
12 pos: usize,
13 fuel: Cell<u32>,
14 events: Vec<Event>,
15}
16
17#[derive(Debug, Clone)]
18pub(super) struct Token {
19 kind: SyntaxKind,
20 text: std::string::String,
21}
22
23impl Token {
24 fn is_trivia(&self) -> bool {
25 matches!(self.kind, SyntaxKind::WHITESPACE | SyntaxKind::Comment)
26 }
27
28 pub(super) fn kind(&self) -> SyntaxKind {
29 self.kind
30 }
31}
32
33#[derive(Debug)]
34pub struct ParseError {
35 pub span: TextRange,
36 pub message: String,
37}
38
39pub fn parse_text(input: &str, entry: TopEntryPoint) -> (GreenNode, Vec<ParseError>) {
40 let tokens = lex(input);
41 let parse_input = tokens
42 .iter()
43 .filter_map(|(token, _span)| (!token.is_trivia()).then_some(token))
44 .cloned()
45 .collect();
46 let output = entry.parse(parse_input);
47 build_tree(tokens, output)
48}
49
50fn build_tree(
51 tokens: Vec<(Token, Range<usize>)>,
52 events: Vec<Event>,
53) -> (GreenNode, Vec<ParseError>) {
54 let mut tokens = tokens.into_iter().peekable();
55 let mut builder = GreenNodeBuilder::new();
56 let mut erros: Vec<ParseError> = Vec::new();
57
58 for event in &events[..events.len() - 1] {
62 match event {
63 Event::Open { kind } => {
64 while !matches!(kind, SyntaxKind::QueryUnit | SyntaxKind::UpdateUnit)
65 && tokens
66 .peek()
67 .map_or(false, |(next, _span)| next.is_trivia())
68 {
69 let (token, _) = tokens.next().unwrap();
70 builder.token(token.kind.into(), &token.text);
71 }
72 builder.start_node((*kind).into());
73 }
74 Event::Error { expected } => {
75 if let Some((_, span)) = tokens.peek() {
76 erros.push(ParseError {
77 span: TextRange::new(
78 TextSize::new(span.start as u32),
79 TextSize::new(span.start as u32),
80 ),
81 message: if expected.is_empty() {
82 "Syntax Error: unexpected token".to_string()
83 } else {
84 format!(
85 "Syntax Error: expected {}",
86 expected
87 .into_iter()
88 .map(|kind| format!("{kind:?}"))
89 .collect::<Vec<_>>()
90 .join(" or ")
91 )
92 },
93 });
94 }
95 }
96 Event::Close => {
97 builder.finish_node();
98 }
99
100 Event::Advance => {
101 while tokens.peek().map_or(false, |(next, _)| next.is_trivia()) {
102 let (token, _) = tokens.next().unwrap();
103 builder.token(token.kind.into(), &token.text);
104 }
105 let (token, _) = tokens.next().unwrap();
106 builder.token(token.kind.into(), &token.text);
107 }
108 }
109 }
110 assert!(matches!(events.last(), Some(Event::Close)));
112 while tokens.peek().map_or(false, |(next, _)| next.is_trivia()) {
113 let (token, _) = tokens.next().unwrap();
114 builder.token(token.kind.into(), &token.text);
115 }
116 builder.finish_node();
117 (builder.finish(), erros)
118}
119
120impl Parser {
121 fn new(input: Vec<Token>) -> Self {
122 Self {
123 tokens: input,
124 pos: 0,
125 fuel: 1024.into(),
126 events: Vec::new(),
127 }
128 }
129}
130
131#[derive(Debug)]
132enum Event {
133 Open { kind: SyntaxKind },
134 Error { expected: Vec<SyntaxKind> },
135 Close,
136 Advance,
137}
138
139struct MarkOpened {
140 index: usize,
141}
142
143impl Parser {
144 fn open(&mut self) -> MarkOpened {
145 let mark = MarkOpened {
146 index: self.events.len(),
147 };
148 self.events.push(Event::Open {
149 kind: SyntaxKind::Error,
150 });
151 mark
152 }
153
154 fn close(&mut self, m: MarkOpened, kind: SyntaxKind) {
155 self.events[m.index] = Event::Open { kind };
156 self.events.push(Event::Close);
157 }
158
159 fn advance(&mut self) {
160 assert!(!self.eof());
161 self.fuel.set(1024);
162 self.events.push(Event::Advance);
163 self.pos += 1;
164 }
165
166 fn eof(&self) -> bool {
167 self.pos == self.tokens.len()
168 }
169
170 fn nth(&self, lookahead: usize) -> SyntaxKind {
171 if self.fuel.get() == 0 {
172 panic!("parser is stuck")
173 }
174 self.fuel.set(self.fuel.get() - 1);
175 self.tokens
176 .get(self.pos + lookahead)
177 .map_or(SyntaxKind::Eof, |it| it.kind)
178 }
179
180 fn at(&self, kind: SyntaxKind) -> bool {
181 self.nth(0) == kind
182 }
183
184 fn at_any(&self, kinds: &[SyntaxKind]) -> bool {
185 let current = self.nth(0);
186 kinds.contains(¤t)
187 }
188
189 fn eat(&mut self, kind: SyntaxKind) -> bool {
190 if self.at(kind) {
191 self.advance();
192 true
193 } else {
194 false
195 }
196 }
197
198 fn expect(&mut self, kind: SyntaxKind) {
199 if self.eat(kind) {
200 return;
201 }
202 self.events.push(Event::Error {
203 expected: vec![kind],
204 });
205 }
206
207 fn advance_with_error(&mut self, expected: Vec<SyntaxKind>) {
208 let m = self.open();
209 self.advance();
210 self.close(m, SyntaxKind::Error);
211 self.events.push(Event::Error { expected });
212 }
213}
214
215#[derive(Debug)]
216pub enum TopEntryPoint {
217 QueryUnit,
218 UpdateUnit,
219}
220
221impl TopEntryPoint {
222 fn parse(&self, input: Vec<Token>) -> Vec<Event> {
223 let mut parser = Parser::new(input);
224 match self {
225 TopEntryPoint::QueryUnit => parse_QueryUnit(&mut parser),
226 TopEntryPoint::UpdateUnit => parse_UpdateUnit(&mut parser),
227 }
228 parser.events
229 }
230}
231
232pub(super) fn lex(text: &str) -> Vec<(Token, Range<usize>)> {
233 let mut lexer = SyntaxKind::lexer(text);
234 let mut tokens = Vec::new();
235
236 while let Some(result) = lexer.next() {
237 tokens.push((
238 Token {
239 kind: result.unwrap_or(SyntaxKind::Error),
240 text: lexer.slice().to_string(),
241 },
242 lexer.span(),
243 ));
244 }
245 tokens
246}
247
248pub fn guess_operation_type(input: &str) -> Option<TopEntryPoint> {
249 let tokens = lex(input);
250 tokens.iter().find_map(|(token, _)| match token.kind {
251 SyntaxKind::SELECT | SyntaxKind::CONSTRUCT | SyntaxKind::ASK | SyntaxKind::DESCRIBE => {
252 Some(TopEntryPoint::QueryUnit)
253 }
254 SyntaxKind::LOAD
255 | SyntaxKind::CLEAR
256 | SyntaxKind::DROP
257 | SyntaxKind::CREATE
258 | SyntaxKind::ADD
259 | SyntaxKind::MOVE
260 | SyntaxKind::COPY
261 | SyntaxKind::INSERT
262 | SyntaxKind::INSERT_DATA
263 | SyntaxKind::DELETE
264 | SyntaxKind::DELETE_DATA
265 | SyntaxKind::DELETE_WHERE => Some(TopEntryPoint::UpdateUnit),
266 _ => None,
267 })
268}
269
270#[cfg(test)]
271mod tests;