1#![doc = include_str!("syn.md")]
2
3mod generated;
4mod syn_ext;
5
6use itertools::Itertools;
7use sql_fun_core::IVec;
8
9use crate::StringSpan;
10
11pub use self::{
12 generated::*,
13 syn_ext::{ListOpt, Opt},
14};
15
16impl ScanToken {
17 pub fn is_ident(&self) -> bool {
19 if let Some(tok) = self.get_token().as_inner() {
20 matches!(tok, crate::syn::Token::Ident)
21 } else {
22 false
23 }
24 }
25
26 pub fn is_dot(&self) -> bool {
28 if let Some(tok) = self.get_token().as_inner() {
29 matches!(tok, crate::syn::Token::Ascii46)
30 } else {
31 false
32 }
33 }
34
35 pub fn is_comment(&self) -> bool {
37 if let Some(tok) = self.get_token().as_inner() {
38 matches!(tok, crate::syn::Token::Comment)
39 } else {
40 false
41 }
42 }
43}
44
45impl TypeName {
46 #[must_use]
48 pub fn full_name(&self) -> std::string::String {
49 let Some(names) = self.get_names().as_inner() else {
50 return std::string::String::from("");
51 };
52 names
53 .iter()
54 .filter_map(|v| v.as_string().get_sval())
55 .join(".")
56 }
57
58 pub fn get_name_span(&self, tokens: &IVec<ScanToken>) -> StringSpan {
60 let location = self.get_location();
61 if location <= 0 {
62 panic!("invalid location {self:?}")
63 }
64 identifier_many_dot_identifier(tokens, location)
65 }
66}
67
68fn identifier_many_dot_identifier(tokens: &IVec<ScanToken>, location: i32) -> StringSpan {
70 let (start_token_index, tok) = tokens
71 .iter()
72 .find_position(|t| t.get_start() == location)
73 .unwrap();
74 let mut result_span = StringSpan::from_scan_token(tok);
75 let names_token = &mut tokens.as_slice()[start_token_index..].iter();
76 let mut expect_ident = true;
77 for tok in names_token {
78 if tok.is_comment() {
79 continue;
80 }
81 if expect_ident {
82 if tok.is_ident() {
83 result_span.extend(&StringSpan::from_scan_token(tok));
84 expect_ident = false;
85 continue;
86 } else {
87 break;
88 }
89 } else if tok.is_dot() {
90 result_span.extend(&StringSpan::from_scan_token(tok));
91 expect_ident = true;
92 continue;
93 } else {
94 break;
95 }
96 }
97 result_span
98}
99
100impl FuncCall {
101 pub fn get_funcname_span(&self, tokens: &IVec<ScanToken>) -> StringSpan {
103 let location = self.get_location();
104 if location <= 0 {
105 panic!("invalid location {self:?}")
106 }
107 identifier_many_dot_identifier(tokens, location)
108 }
109}