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