1use crate::{SqlLanguage, kind::SqlSyntaxKind};
2use oak_core::{
3 GreenNode, OakError, Parser, ParserState, TextEdit, TokenType,
4 parser::{
5 ParseCache, ParseOutput, parse_with_lexer,
6 pratt::{Associativity, Pratt, PrattParser, binary},
7 },
8 source::Source,
9};
10
11pub struct SqlParser<'config> {
13 pub(crate) config: &'config SqlLanguage,
14}
15
16type State<'a, S> = ParserState<'a, SqlLanguage, S>;
17
18impl<'config> Pratt<SqlLanguage> for SqlParser<'config> {
19 fn primary<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> &'a GreenNode<'a, SqlLanguage> {
20 use crate::kind::SqlSyntaxKind::*;
21 let cp = state.checkpoint();
22 match state.peek_kind() {
23 Some(Identifier_) => {
24 state.bump();
25 state.finish_at(cp, Identifier.into())
26 }
27 Some(NumberLiteral) | Some(StringLiteral) | Some(BooleanLiteral) | Some(NullLiteral) => {
28 state.bump();
29 state.finish_at(cp, Expression.into())
30 }
31 Some(LeftParen) => {
32 state.bump();
33 PrattParser::parse(state, 0, self);
34 state.expect(RightParen).ok();
35 state.finish_at(cp, Expression.into())
36 }
37 _ => {
38 state.bump();
39 state.finish_at(cp, ErrorNode.into())
40 }
41 }
42 }
43
44 fn prefix<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> &'a GreenNode<'a, SqlLanguage> {
45 self.primary(state)
46 }
47
48 fn infix<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>, left: &'a GreenNode<'a, SqlLanguage>, min_precedence: u8) -> Option<&'a GreenNode<'a, SqlLanguage>> {
49 use crate::kind::SqlSyntaxKind::*;
50 let kind = state.peek_kind()?;
51
52 let (prec, assoc) = match kind {
53 Or => (1, Associativity::Left),
54 And => (2, Associativity::Left),
55 Equal | NotEqual | Less | Greater | LessEqual | GreaterEqual | Like | In | Between | Is => (3, Associativity::Left),
56 Plus | Minus => (10, Associativity::Left),
57 Star | Slash | Percent => (11, Associativity::Left),
58 _ => return None,
59 };
60
61 if prec < min_precedence {
62 return None;
63 }
64
65 Some(binary(state, left, kind, prec, assoc, Expression.into(), |s, p| PrattParser::parse(s, p, self)))
66 }
67}
68
69impl<'config> SqlParser<'config> {
70 pub fn new(config: &'config SqlLanguage) -> Self {
71 Self { config }
72 }
73
74 pub(crate) fn parse_root_internal<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<&'a GreenNode<'a, SqlLanguage>, OakError> {
75 let cp = state.checkpoint();
76 while state.not_at_end() {
77 if state.current().map(|t| t.kind.is_ignored()).unwrap_or(false) {
78 state.advance();
79 continue;
80 }
81 self.parse_statement(state)?;
82 }
83 Ok(state.finish_at(cp, SqlSyntaxKind::Root.into()))
84 }
85
86 fn parse_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
87 use crate::kind::SqlSyntaxKind::*;
88 match state.peek_kind() {
89 Some(Select) => self.parse_select(state)?,
90 Some(Insert) => self.parse_insert(state)?,
91 Some(Update) => self.parse_update(state)?,
92 Some(Delete) => self.parse_delete(state)?,
93 Some(Create) => self.parse_create(state)?,
94 Some(Drop) => self.parse_drop(state)?,
95 Some(Alter) => self.parse_alter(state)?,
96 _ => {
97 state.advance_until(Semicolon);
98 state.eat(Semicolon);
99 }
100 }
101 Ok(())
102 }
103
104 fn parse_select<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
105 use crate::kind::SqlSyntaxKind::*;
106 let cp = state.checkpoint();
107 state.expect(Select).ok();
108 state.advance_until(From);
109 state.expect(From).ok();
110 state.expect(Identifier_).ok(); if state.eat(Where) {
112 PrattParser::parse(state, 0, self);
113 }
114 state.eat(Semicolon);
115 state.finish_at(cp, SelectStatement.into());
116 Ok(())
117 }
118
119 fn parse_insert<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
120 let cp = state.checkpoint();
121 state.bump(); state.advance_until(crate::kind::SqlSyntaxKind::Semicolon);
123 state.eat(crate::kind::SqlSyntaxKind::Semicolon);
124 state.finish_at(cp, crate::kind::SqlSyntaxKind::InsertStatement.into());
125 Ok(())
126 }
127
128 fn parse_update<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
129 let cp = state.checkpoint();
130 state.bump(); state.advance_until(crate::kind::SqlSyntaxKind::Semicolon);
132 state.eat(crate::kind::SqlSyntaxKind::Semicolon);
133 state.finish_at(cp, crate::kind::SqlSyntaxKind::UpdateStatement.into());
134 Ok(())
135 }
136
137 fn parse_delete<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
138 let cp = state.checkpoint();
139 state.bump(); state.advance_until(crate::kind::SqlSyntaxKind::Semicolon);
141 state.eat(crate::kind::SqlSyntaxKind::Semicolon);
142 state.finish_at(cp, crate::kind::SqlSyntaxKind::DeleteStatement.into());
143 Ok(())
144 }
145
146 fn parse_create<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
147 let cp = state.checkpoint();
148 state.bump(); state.advance_until(crate::kind::SqlSyntaxKind::Semicolon);
150 state.eat(crate::kind::SqlSyntaxKind::Semicolon);
151 state.finish_at(cp, crate::kind::SqlSyntaxKind::CreateStatement.into());
152 Ok(())
153 }
154
155 fn parse_drop<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
156 let cp = state.checkpoint();
157 state.bump(); state.advance_until(crate::kind::SqlSyntaxKind::Semicolon);
159 state.eat(crate::kind::SqlSyntaxKind::Semicolon);
160 state.finish_at(cp, crate::kind::SqlSyntaxKind::DropStatement.into());
161 Ok(())
162 }
163
164 fn parse_alter<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
165 let cp = state.checkpoint();
166 state.bump(); state.advance_until(crate::kind::SqlSyntaxKind::Semicolon);
168 state.eat(crate::kind::SqlSyntaxKind::Semicolon);
169 state.finish_at(cp, crate::kind::SqlSyntaxKind::AlterStatement.into());
170 Ok(())
171 }
172}
173
174impl<'config> Parser<SqlLanguage> for SqlParser<'config> {
175 fn parse<'a, S: Source + ?Sized>(&self, text: &'a S, edits: &[TextEdit], cache: &'a mut impl ParseCache<SqlLanguage>) -> ParseOutput<'a, SqlLanguage> {
176 let lexer = crate::lexer::SqlLexer::new(self.config);
177 parse_with_lexer(&lexer, text, edits, cache, |state| self.parse_root_internal(state))
178 }
179}