Skip to main content

ll_sparql_parser/parser/
mod.rs

1mod 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    // Special case: pop the last `Close` event to ensure
59    // that the stack is non-empty inside the loop.
60    // assert!(matches!(events.pop(), Some(Event::Close)));
61    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    // Eat trailing trivia tokens
111    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(&current)
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;