databend_common_ast/parser/
input.rs1use std::ops::Range;
16use std::ops::RangeFrom;
17use std::ops::RangeFull;
18use std::ops::RangeTo;
19
20use enum_as_inner::EnumAsInner;
21
22use crate::parser::token::Token;
23use crate::parser::Backtrace;
24
25#[derive(Debug, Clone, Copy)]
28pub struct Input<'a> {
29 pub tokens: &'a [Token<'a>],
30 pub dialect: Dialect,
31 pub mode: ParseMode,
32 pub backtrace: &'a Backtrace,
33}
34
35impl<'a> std::ops::Deref for Input<'a> {
36 type Target = [Token<'a>];
37
38 fn deref(&self) -> &Self::Target {
39 self.tokens
40 }
41}
42
43impl nom::InputLength for Input<'_> {
44 fn input_len(&self) -> usize {
45 self.tokens.input_len()
46 }
47}
48
49impl nom::Offset for Input<'_> {
50 fn offset(&self, second: &Self) -> usize {
51 let fst = self.tokens.as_ptr();
52 let snd = second.tokens.as_ptr();
53
54 (snd as usize - fst as usize) / std::mem::size_of::<Token>()
55 }
56}
57
58impl nom::Slice<Range<usize>> for Input<'_> {
59 fn slice(&self, range: Range<usize>) -> Self {
60 Input {
61 tokens: &self.tokens[range],
62 ..*self
63 }
64 }
65}
66
67impl nom::Slice<RangeTo<usize>> for Input<'_> {
68 fn slice(&self, range: RangeTo<usize>) -> Self {
69 Input {
70 tokens: &self.tokens[range],
71 ..*self
72 }
73 }
74}
75
76impl nom::Slice<RangeFrom<usize>> for Input<'_> {
77 fn slice(&self, range: RangeFrom<usize>) -> Self {
78 Input {
79 tokens: &self.tokens[range],
80 ..*self
81 }
82 }
83}
84
85impl nom::Slice<RangeFull> for Input<'_> {
86 fn slice(&self, _: RangeFull) -> Self {
87 *self
88 }
89}
90
91#[derive(Clone, Debug)]
92pub struct WithSpan<'a, T> {
93 pub(crate) span: Input<'a>,
94 pub(crate) elem: T,
95}
96
97#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, EnumAsInner)]
98pub enum ParseMode {
99 #[default]
100 Default,
101 Template,
102}
103
104#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, EnumAsInner)]
105pub enum Dialect {
106 #[default]
107 PostgreSQL,
108 MySQL,
109 Hive,
110 PRQL,
111 Experimental,
112}
113
114impl Dialect {
115 pub fn is_ident_quote(&self, c: char) -> bool {
116 match self {
117 Dialect::MySQL => c == '`',
118 Dialect::Hive => c == '`',
119 Dialect::Experimental | Dialect::PostgreSQL | Dialect::PRQL => c == '"' || c == '`',
121 }
122 }
123
124 pub fn is_string_quote(&self, c: char) -> bool {
125 match self {
126 Dialect::MySQL => c == '\'' || c == '"',
127 Dialect::Hive => c == '\'' || c == '"',
128 Dialect::Experimental | Dialect::PostgreSQL | Dialect::PRQL => c == '\'',
129 }
130 }
131
132 pub fn substr_index_zero_literal_as_one(&self) -> bool {
133 match self {
134 Dialect::MySQL => false,
135 Dialect::Hive => true,
136 Dialect::Experimental | Dialect::PostgreSQL | Dialect::PRQL => false,
137 }
138 }
139
140 pub fn default_ident_quote(&self) -> char {
141 match self {
142 Dialect::MySQL | Dialect::Hive => '`',
143 Dialect::Experimental | Dialect::PostgreSQL | Dialect::PRQL => '"',
144 }
145 }
146}