Skip to main content

rust_store_core/pipeline/
token.rs

1//! 词法分析:GQL 字符串 → Token 序列
2
3use serde_json::{Map, Value};
4
5#[derive(Debug, Clone, PartialEq)]
6pub struct Token {
7    pub kind: &'static str,
8    pub value: String,
9}
10
11fn is_ident_start(c: char) -> bool {
12    c.is_ascii_alphabetic() || c == '_' || c == '$'
13}
14
15fn is_ident_char(c: char) -> bool {
16    c.is_ascii_alphanumeric() || c == '_' || c == '$' || c == '.'
17}
18
19fn is_ref_char(c: char) -> bool {
20    c.is_ascii_alphanumeric() || c == '_'
21}
22
23pub fn tokenize(gql: &str) -> Vec<Token> {
24    let chars: Vec<char> = gql.chars().collect();
25    let n = chars.len();
26    let mut tokens = Vec::new();
27    let mut i = 0;
28    while i < n {
29        let ch = chars[i];
30        // 空白
31        if ch.is_whitespace() {
32            i += 1;
33            continue;
34        }
35        // 标点
36        if "(){},:".contains(ch) {
37            tokens.push(Token {
38                kind: "p",
39                value: ch.to_string(),
40            });
41            i += 1;
42            continue;
43        }
44        // 标识符(模型名/字段名/关系名,支持点号嵌套)
45        if is_ident_start(ch) {
46            let mut v = String::new();
47            while i < n && is_ident_char(chars[i]) {
48                v.push(chars[i]);
49                i += 1;
50            }
51            tokens.push(Token {
52                kind: "id",
53                value: v,
54            });
55            continue;
56        }
57        // 参数引用 @xxx
58        if ch == '@' {
59            let mut v = String::from("@");
60            i += 1;
61            while i < n && is_ref_char(chars[i]) {
62                v.push(chars[i]);
63                i += 1;
64            }
65            tokens.push(Token {
66                kind: "ref",
67                value: v,
68            });
69            continue;
70        }
71        i += 1; // 跳过未知字符
72    }
73    tokens
74}
75
76pub fn token_to_value(t: &Token) -> Value {
77    Value::Object(Map::from_iter([
78        ("t".to_string(), Value::String(t.kind.to_string())),
79        ("v".to_string(), Value::String(t.value.clone())),
80    ]))
81}