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