Форум программистов, компьютерный форум, киберфорум
Rust
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.73/15: Рейтинг темы: голосов - 15, средняя оценка - 4.73
 Аватар для pgb
-508 / 32 / 0
Регистрация: 22.09.2015
Сообщений: 1,232

Своя реализация регулярных выражений. Реалити разработка, как говорится учитесь пока я жив :)

16.06.2024, 15:01. Показов 3858. Ответов 21
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Итак, для разработки своих будущих проектов мне нужен быстрый парсинг с удобным для меня функционалом. Есть же регулярные выражения скажете вы, да есть, но тоже самое можно сделать намного проще и удобнее и это я вам докажу в этой теме. Кроме того при использовании регулярных выражений из стандартной библиотеки подключаются куча всего разного, что увеличивает исходный код ну и скорость я думаю от этого тоже замедляется. Короче споры тут не уместны я приступаю к разработке своей реализации регулярных выражения на Rust.

На разработку может уйти некоторое время, т.к. я только начинаю писать на Rust, приходится попутно всё изучать, кроме того у меня есть и другие дела, проекты, так же при решении тех или иных микро задач будут возникать трудности, которые я обычно обдумываю занимаясь другими делами, даже когда отдыхаю, смотрю например кино и тд., мне может придти мысль как что можно сделать и затем проверяю это, поэтому всё будет делаться по мере возможности. Но думаю за пару месяцев +- управлюсь.

Назову модуль пока notch, потом название возможно поменяется.

Первоначально надо придумать синтаксис для поиска подстрок:

> - начало строки, в начале(как^);
< - конец строки, в конце(как $);
s - пробел(как \s);
t - табуляция(как \t);
n - (NL) новая строка(как \n);
c - (CR) возврат каретки(как \r);
i - число integer(как \d);
f - число с точкой float;
l - буква(как \w);
L - заглавная буква;
w - слово;
W - слово заглавными буквами;
m - спецсимвол;
a - любой символ(как .);
{text} - конкретный текст;
[zzz] - возможные совпадения(подразумевается "или"), где zzz - шаблон;
(zzz) - захват подстроки, где zzz - шаблон;
* - ноль или более раз повторов;
+ - один или более раз повторов;
*n - ноль или более раз, но не более n;
+n - один или более раз, но не более n;
:n - где n - количество раз повторов;
! - отрицание совпадения;
| - или;
?zzz? - проверка, где zzz - шаблон
#n - захваченная подстрока

Данный синтаксис придумал только что при написании этого сообщения, возможно потом поменяю, что-то добавлю...
Я сделал так чтобы было без использования управляющих символов \n,\r,\s,\w и тд. а использовались простые буквы, ведь это просто шаблон, в котором мы можем описать искомые символы своими значениями и синтаксисом для логики.

Старался сделать так чтобы было привычно и более удобнее чем в существующих регулярных выражениях.

Правда есть нюанс. Как указывать конкретный спецсимвол который используется в синтаксисе шаблона: *+:!|?#(){}[]
Я над этим вопросом ещё подумаю, может выбрать какой либо спецсимвол после которого писать нужный, например ~:
~({нужный ~{мне~} текст}~) - то есть будет искаться "(нужный {мне} текст)" в круглых скобках с фигурными внутри конкретного текста
~#[iL]:4 - что будет соответствовать "#00AB" двухбайтному числу в шестнадцатеричной форме
возможно так и сделаю, но это не точно
1
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
16.06.2024, 15:01
Ответы с готовыми решениями:

Реализация алгоритма поиска в http ответе с помощью регулярных выражений
На входе: 1--------------------------------------------------------------------------------------- HTTP/1.0 401 Unauthorized ...

Как оптимизировать применение регулярных выражений
Как оптимизировать следующий код? string a2 = Regex.Replace(x, p, @&quot;$4&quot;, RegexOptions.IgnoreCase); string a3 = Regex.Replace(x, p,...

Как происходит проверка регулярных выражений в Regex.IsMatch?
Не разберусь что-то никак. Вот простой пример: public bool IsCyrillic(string pattern) { Regex rgx =...

21
Супер-модератор
Эксперт функциональных языков программированияЭксперт Python
 Аватар для Catstail
38173 / 21108 / 4307
Регистрация: 12.02.2012
Сообщений: 34,707
Записей в блоге: 14
16.06.2024, 15:04
А чем это лучше стандартных регэкспов?
2
 Аватар для pgb
-508 / 32 / 0
Регистрация: 22.09.2015
Сообщений: 1,232
16.06.2024, 15:38  [ТС]
Цитата Сообщение от Catstail Посмотреть сообщение
А чем это лучше стандартных регэкспов?
На подобные вопросы я больше не отвечаю, объяснять вам бесполезно..
Цитата Сообщение от pgb Посмотреть сообщение
Есть же регулярные выражения скажете вы, да есть, но тоже самое можно сделать намного проще и удобнее и это я вам докажу в этой теме. Кроме того при использовании регулярных выражений из стандартной библиотеки подключаются куча всего разного, что увеличивает исходный код ну и скорость я думаю от этого тоже замедляется.
0
Супер-модератор
Эксперт функциональных языков программированияЭксперт Python
 Аватар для Catstail
38173 / 21108 / 4307
Регистрация: 12.02.2012
Сообщений: 34,707
Записей в блоге: 14
16.06.2024, 16:08
pgb, 1) не надо высокомерно хамить 2) из описания не видно, что "намного проще"... Впрочем, возможно. Но только ценой потери части стандартных возможностей регэкспов. Если вы реализуете только "поиск подстрок", то это всего лишь часть функций регулярных выражений. В любом случае сказать, что "намного проще" вы можете только в случае демонстрации десятка-двух сопоставляющих примеров:

- вот стандартное решение (видите, как громоздко!)
- а вот мое решение (видите, как коротко и просто!)

Цитата Сообщение от pgb Посмотреть сообщение
Старался сделать так чтобы было привычно и более удобнее чем в существующих регулярных выражениях.
- кому "привычнее и удобнее"? Это очень субъективная оценка.

Цитата Сообщение от pgb Посмотреть сообщение
Кроме того при использовании регулярных выражений из стандартной библиотеки подключаются куча всего разного, что увеличивает исходный код ну и скорость я думаю от этого тоже замедляется.
- откуда такие сведения?

Цитата Сообщение от pgb Посмотреть сообщение
Короче споры тут не уместны
- а форум - это площадка для споров. Если вам не нужно обсуждение, а реклама, так с этим не сюда.

Цитата Сообщение от pgb Посмотреть сообщение
Данный синтаксис придумал только что при написании этого сообщения
- и это настораживает...

Итог: реализуйте и сравнивайте со стандартными решениями. Получится - прекрасно... Флаг в руки.
9
Эксперт .NET
 Аватар для Rius
13114 / 7675 / 1674
Регистрация: 25.05.2015
Сообщений: 23,403
Записей в блоге: 14
16.06.2024, 16:16
Чем бы пустобрёх не тешился, лишь бы старые проекты не завершать.
8
 Аватар для pgb
-508 / 32 / 0
Регистрация: 22.09.2015
Сообщений: 1,232
16.06.2024, 22:29  [ТС]
Получение токенов шаблона, пока черновой вариант. Есть баг при использовании +, другие пока не проверял. Так же есть мысли по улучшению кода.
Rust
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
#[derive(Debug, PartialEq)]
enum TokenBase {
    Space,
    Tab,
    NewLine,
    CarriageReturn,
    Integer,
    Float,
    Lowercase,
    Uppercase,
    Word,
    CapitalWord,
    SpecialChar,
    AnyChar
}
 
#[derive(Debug, PartialEq)]
enum Token {
    Start,
    Space,
    Tab,
    NewLine,
    CarriageReturn,
    Integer,
    Float,
    Lowercase,
    Uppercase,
    Word,
    CapitalWord,
    SpecialChar,
    AnyChar,
    Or,
    Not,
    End,
    ZeroOrMore,
    OneOrMore,
    ZeroOrMoreN(u16),
    OneOrMoreN(u16),
    Repeat(u16),
    Text(String),
    Check(String),
    Substring(u16),
    Capture(String),
    Variants(Vec<TokenBase>)
}
 
 
fn pattern_v(input: &str) -> Vec<TokenBase> {
    let mut tokens = Vec::new();
    let mut chars = input.chars();
 
    while let Some(c) = chars.next() {
        match c {
            's' => tokens.push(TokenBase::Space),
            't' => tokens.push(TokenBase::Tab),
            'n' => tokens.push(TokenBase::NewLine),
            'c' => tokens.push(TokenBase::CarriageReturn),
            'i' => tokens.push(TokenBase::Integer),
            'f' => tokens.push(TokenBase::Float),
            'l' => tokens.push(TokenBase::Lowercase),
            'L' => tokens.push(TokenBase::Uppercase),
            'w' => tokens.push(TokenBase::Word),
            'W' => tokens.push(TokenBase::CapitalWord),
            'm' => tokens.push(TokenBase::SpecialChar),
            'a' => tokens.push(TokenBase::AnyChar),
            _ => panic!("Ошибка шаблона BBB")
        }
    }
    tokens
}
 
fn pattern(input: &str) -> Vec<Token> {
    let mut tokens = Vec::new();
    let mut chars = input.chars();
 
    while let Some(c) = chars.next() {
        println!("=={}",c);
        match c {
            '>' => tokens.push(Token::Start),
            's' => tokens.push(Token::Space),
            't' => tokens.push(Token::Tab),
            'n' => tokens.push(Token::NewLine),
            'c' => tokens.push(Token::CarriageReturn),
            'i' => tokens.push(Token::Integer),
            'f' => tokens.push(Token::Float),
            'l' => tokens.push(Token::Lowercase),
            'L' => tokens.push(Token::Uppercase),
            'w' => tokens.push(Token::Word),
            'W' => tokens.push(Token::CapitalWord),
            'm' => tokens.push(Token::SpecialChar),
            'a' => tokens.push(Token::AnyChar),
            '!' => tokens.push(Token::Not),
            '|' => tokens.push(Token::Or),
            '<' => tokens.push(Token::End),
            '*' => {
                if let Some(c) = chars.next() {
                    if c.is_digit(10) {
                        let mut n = String::new();
                        n.push(c);
                        while let Some(c) = chars.next() {
                            if !c.is_digit(10) {
                                chars.next_back();break;
                            }
                            n.push(c);
                        }
                        tokens.push(Token::ZeroOrMoreN(n.parse().unwrap()));
                    } else {
                        chars.next_back();
                        tokens.push(Token::ZeroOrMore);
                    }
                } else {
                    tokens.push(Token::ZeroOrMore);
                }
            }
            '+' => {
                if let Some(c) = chars.next() {
                    if c.is_digit(10) {
                        let mut n = String::new();
                        n.push(c);
                        while let Some(c) = chars.next() {
                            if !c.is_digit(10) {
                                chars.next_back();break;
                            }
                            n.push(c);
                        }
                        tokens.push(Token::OneOrMoreN(n.parse().unwrap()));
                    } else {
                        if let Some(c) = chars.next_back() {
                            println!("<<{}",c);
                        }
                        tokens.push(Token::OneOrMore);
                    }
                } else {
                    chars.next_back();
                    tokens.push(Token::OneOrMore);
                }
            }
            ':' => {
                let mut n = String::new();
                while let Some(c) = chars.next() {
                    if !c.is_digit(10) {
                        chars.next_back();break;
                    }
                    n.push(c);
                }
                tokens.push(Token::Repeat(n.parse().unwrap()));
            }
            '{' => {
                let mut text = String::new();
                while let Some(c) = chars.next() {
                    if c == '}' {break;}
                    text.push(c);
                }
                tokens.push(Token::Text(text));
            }
            '[' => {
                let mut variants = String::new();
                while let Some(c) = chars.next() {
                    if c == ']' {break;}
                    variants.push(c);
                }
                tokens.push(Token::Variants(pattern_v(&variants)));
            }
            '#' => {
                if let Some(c) = chars.next() {
                    if c.is_digit(10) {
                        let mut n = String::new();
                        n.push(c);
                        while let Some(c) = chars.next() {
                            if !c.is_digit(10) {
                                chars.next_back();break;
                            }
                            n.push(c);
                        }
                        tokens.push(Token::Substring(n.parse().unwrap()));
                    } else {
                        chars.next_back();
                    }
                }
            }
            '(' => {
                let mut capture = String::new();
                while let Some(c) = chars.next() {
                    if c == ')' {break;}
                    capture.push(c);
                }
                tokens.push(Token::Capture(capture));
            }
            '?' => {
                let mut check = String::new();
                while let Some(c) = chars.next() {
                    if c == '?' {break;}
                    check.push(c);
                }
                tokens.push(Token::Check(check));
            }
            _ => panic!("Ошибка шаблона '{}'",c)
        }
    }
 
    tokens
}
 
fn main() {
    let input = "t{abc}";
    let tokens = pattern(input);
    println!("{:#?}", tokens);
}
Добавлено через 40 минут
Вопрос: Как вернутся назад на один символ в итераторе std::str::Chars?

Добавлено через 2 часа 31 минуту
Улучшенный код получения токенов шаблона
Rust
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
use std::str::Chars;
use std::iter::Peekable;
 
#[derive(Debug, PartialEq)]
enum Sign {
    Start,
    Space,
    Tab,
    NewLine,
    CarriageReturn,
    Integer,
    Float,
    Lowercase,
    Uppercase,
    Word,
    CapitalWord,
    SpecialChar,
    AnyChar,
    Or,
    Not,
    End
}
 
#[derive(Debug, PartialEq)]
enum Token {
    Template(Sign),
    ZeroOrMore(u16),
    OneOrMore(u16),
    Repeat(u16),
    Text(String),
    Check(String),
    Substring(u16),
    Capture(String),
    Variants(Vec<Sign>)
}
 
 
fn pattern_v(input: &str) -> Vec<Sign> {
    let mut tokens = Vec::new();
    let mut chars = input.chars();
 
    while let Some(c) = chars.next() {
        match c {
            's' => tokens.push(Sign::Space),
            't' => tokens.push(Sign::Tab),
            'n' => tokens.push(Sign::NewLine),
            'c' => tokens.push(Sign::CarriageReturn),
            'i' => tokens.push(Sign::Integer),
            'f' => tokens.push(Sign::Float),
            'l' => tokens.push(Sign::Lowercase),
            'L' => tokens.push(Sign::Uppercase),
            'w' => tokens.push(Sign::Word),
            'W' => tokens.push(Sign::CapitalWord),
            'm' => tokens.push(Sign::SpecialChar),
            'a' => tokens.push(Sign::AnyChar),
            _ => panic!("Ошибка шаблона BBB")
        }
    }
    tokens
}
 
fn pattern(input: &str) -> Vec<Token> {
    let mut tokens = Vec::new();
    let mut chars = input.chars().peekable();
 
    while let Some(c) = chars.next() {
        println!("=={}",c);
        match c {
            '>' => tokens.push(Token::Template(Sign::Start)),
            's' => tokens.push(Token::Template(Sign::Space)),
            't' => tokens.push(Token::Template(Sign::Tab)),
            'n' => tokens.push(Token::Template(Sign::NewLine)),
            'c' => tokens.push(Token::Template(Sign::CarriageReturn)),
            'i' => tokens.push(Token::Template(Sign::Integer)),
            'f' => tokens.push(Token::Template(Sign::Float)),
            'l' => tokens.push(Token::Template(Sign::Lowercase)),
            'L' => tokens.push(Token::Template(Sign::Uppercase)),
            'w' => tokens.push(Token::Template(Sign::Word)),
            'W' => tokens.push(Token::Template(Sign::CapitalWord)),
            'm' => tokens.push(Token::Template(Sign::SpecialChar)),
            'a' => tokens.push(Token::Template(Sign::AnyChar)),
            '!' => tokens.push(Token::Template(Sign::Not)),
            '|' => tokens.push(Token::Template(Sign::Or)),
            '<' => tokens.push(Token::Template(Sign::End)),
            '*' => {
                if let Some(num) = getnum(&mut chars) {
                    tokens.push(Token::ZeroOrMore(num));
                } else {
                    tokens.push(Token::ZeroOrMore(0));
                }
            }
            '+' => {
                if let Some(num) = getnum(&mut chars) {
                    tokens.push(Token::OneOrMore(num));
                } else {
                    tokens.push(Token::OneOrMore(0));
                }
            }
            ':' => {
                if let Some(num) = getnum(&mut chars) {
                    tokens.push(Token::Repeat(num));
                } else {
                    panic!("После знака ':' должно быть число");
                }
            }
            '{' => {
                let str = getstr(&mut chars,'}');
                tokens.push(Token::Text(str));
            }
            '[' => {
                let str = getstr(&mut chars,']');
                tokens.push(Token::Variants(pattern_v(&str)));
            }
            '#' => {
                if let Some(num) = getnum(&mut chars) {
                    tokens.push(Token::Substring(num));
                } else {
                    panic!("После знака '#' должно быть число");
                }
            }
            '(' => {
                let str = getstr(&mut chars,')');
                tokens.push(Token::Capture(str));
            }
            '?' => {
                let str = getstr(&mut chars,'?');
                tokens.push(Token::Check(str));
            }
            _ => panic!("Ошибка шаблона '{}'",c)
        }
    }
 
    tokens
}
 
fn getstr(chr: &mut Peekable<Chars<'_>>, sym: char) -> String {
    let mut res = String::new();
    while let Some(ch) = chr.peek() {
        if ch == &sym {chr.next();break;}
        res.push(*ch);chr.next();
    }
    res
}
 
fn getnum(chr: &mut Peekable<Chars<'_>>) -> Option<u16> {
    let mut res = String::new();
    while let Some(ch) = chr.peek() {
        if ch.is_digit(10) {
            res.push(*ch);
            chr.next();
        }else{break;}
    }
    res.parse().ok()
}
 
fn main() {
    let input = "t+{abc}";
    let tokens = pattern(input);
    println!("{:#?}", tokens);
    let mut chars=input.chars().peekable();
    println!("{:?}",getstr(&mut chars,'}'));
}
Добавлено через 1 час 1 минуту
Ещё немного улучшил, прогрессирую в отличие от тех кто в меня свои какашки кидают..
Rust
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
use std::str::Chars;
use std::iter::Peekable;
 
#[derive(Debug, PartialEq)]
enum Sign {
    Start,
    Space,
    Tab,
    NewLine,
    CarriageReturn,
    Integer,
    Float,
    Lowercase,
    Uppercase,
    Word,
    CapitalWord,
    SpecialChar,
    AnyChar,
    Or,
    Not,
    End
}
 
#[derive(Debug, PartialEq)]
enum Token {
    Template(Sign),
    ZeroOrMore(u16),
    OneOrMore(u16),
    Repeat(u16),
    Text(String),
    Check(String),
    Substring(u16),
    Capture(String),
    Variants(Vec<Sign>)
}
 
 
fn variant(input: &str) -> Vec<Sign> {
    let mut tokens = Vec::new();
    let mut chars = input.chars();
 
    while let Some(c) = chars.next() {
        match c {
            's' => tokens.push(Sign::Space),
            't' => tokens.push(Sign::Tab),
            'n' => tokens.push(Sign::NewLine),
            'c' => tokens.push(Sign::CarriageReturn),
            'i' => tokens.push(Sign::Integer),
            'f' => tokens.push(Sign::Float),
            'l' => tokens.push(Sign::Lowercase),
            'L' => tokens.push(Sign::Uppercase),
            'w' => tokens.push(Sign::Word),
            'W' => tokens.push(Sign::CapitalWord),
            'm' => tokens.push(Sign::SpecialChar),
            'a' => tokens.push(Sign::AnyChar),
            _ => panic!("\nНе допустимый символ '{}' варианта [{}]\n",c,input)
        }
    }
    tokens
}
 
fn pattern(input: &str) -> Vec<Token> {
    let mut tokens = Vec::new();
    let mut chars = input.chars().peekable();
 
    while let Some(c) = chars.next() {
        match c {
            '>' => tokens.push(Token::Template(Sign::Start)),
            's' => tokens.push(Token::Template(Sign::Space)),
            't' => tokens.push(Token::Template(Sign::Tab)),
            'n' => tokens.push(Token::Template(Sign::NewLine)),
            'c' => tokens.push(Token::Template(Sign::CarriageReturn)),
            'i' => tokens.push(Token::Template(Sign::Integer)),
            'f' => tokens.push(Token::Template(Sign::Float)),
            'l' => tokens.push(Token::Template(Sign::Lowercase)),
            'L' => tokens.push(Token::Template(Sign::Uppercase)),
            'w' => tokens.push(Token::Template(Sign::Word)),
            'W' => tokens.push(Token::Template(Sign::CapitalWord)),
            'm' => tokens.push(Token::Template(Sign::SpecialChar)),
            'a' => tokens.push(Token::Template(Sign::AnyChar)),
            '!' => tokens.push(Token::Template(Sign::Not)),
            '|' => tokens.push(Token::Template(Sign::Or)),
            '<' => tokens.push(Token::Template(Sign::End)),
            '*' => {
                if let Some(num) = getnum(&mut chars) {
                    tokens.push(Token::ZeroOrMore(num));
                } else {
                    tokens.push(Token::ZeroOrMore(0));
                }
            }
            '+' => {
                if let Some(num) = getnum(&mut chars) {
                    tokens.push(Token::OneOrMore(num));
                } else {
                    tokens.push(Token::OneOrMore(0));
                }
            }
            ':' => {
                if let Some(num) = getnum(&mut chars) {
                    tokens.push(Token::Repeat(num));
                } else {
                    panic!("После знака ':' должно быть число");
                }
            }
            '{' => {
                let str = getstr(&mut chars,'}');
                tokens.push(Token::Text(str));
            }
            '[' => {
                let str = getstr(&mut chars,']');
                tokens.push(Token::Variants(variant(&str)));
            }
            '#' => {
                if let Some(num) = getnum(&mut chars) {
                    tokens.push(Token::Substring(num));
                } else {
                    panic!("После знака '#' должно быть число");
                }
            }
            '(' => {
                let str = getstr(&mut chars,')');
                tokens.push(Token::Capture(str));
            }
            '?' => {
                let str = getstr(&mut chars,'?');
                tokens.push(Token::Check(str));
            }
            _ => panic!("Ошибка шаблона '{}'",c)
        }
    }
    tokens
}
 
fn getstr(chr: &mut Peekable<Chars<'_>>, sym: char) -> String {
    let mut res = String::new();
    let mut cha:char;
    while let Some(ch) = chr.next() {
        cha=ch;
        if cha == sym {break;}
        else if cha == '~' {
           cha= chr.next().unwrap_or('~');
        }
        res.push(cha);
    }
    res
}
 
fn getnum(chr: &mut Peekable<Chars<'_>>) -> Option<u16> {
    let mut res = String::new();
    while let Some(ch) = chr.peek() {
        if ch.is_digit(10) {
            res.push(*ch);
            chr.next();
        }else{break;}
    }
    res.parse().ok()
}
 
fn main() {
    let input = "t+{ab~}c}[iL]:4";
    let tokens = pattern(input);
    println!("{:#?}", tokens);
    //let mut chars=input.chars().peekable();
    //println!("{:?}",getstr(&mut chars,'}'));
}
ЗЫ. На следующей неделе меня наверно не будет, ягоды говорят созрели, поеду на дачу

Добавлено через 12 минут
Цитата Сообщение от Rius Посмотреть сообщение
Чем бы пустобрёх не тешился, лишь бы старые проекты не завершать.
Фреймворк я завершил. Сейчас с домашними делами разберусь, потом буду сайт проекта, форум и др. на фреймворке настраивать. По не многу изучаю Rust, чтобы попрактиковаться и полезные модули функции на будущее написать, в выходной день почему бы не поделать. Мне интересно, что то новое, а с фреймворком я ещё успею поработать, когда долго занимаешься одним большим проектом, рутина надоедает, появляется что-то интересное поэтому хочется поэкспериментировать.
Так что не вам меня судить, сами ни на что не способны, а осуждают..
0
 Аватар для pgb
-508 / 32 / 0
Регистрация: 22.09.2015
Сообщений: 1,232
16.06.2024, 23:51  [ТС]
*********
0
Модератор
 Аватар для Curry
5158 / 3482 / 536
Регистрация: 01.06.2013
Сообщений: 7,549
Записей в блоге: 9
17.06.2024, 02:13
pgb, воздерживайтесь от оскорблений.
Rius, не провоцируйте его.
0
Заблокирован
21.06.2024, 12:44
Любят у нас люди человека опустить. Из зависти одной только любят.
Ну сделал человек что-то, ну хочет поделиться своими эмоциями. Так нет, надо в него обязательно плюнуть...
0
Супер-модератор
Эксперт функциональных языков программированияЭксперт Python
 Аватар для Catstail
38173 / 21108 / 4307
Регистрация: 12.02.2012
Сообщений: 34,707
Записей в блоге: 14
22.06.2024, 06:53
Гай, не так. Человек выступил очень претенциозно (одно "учитесь, пока я жив" чего стоит...) Но тему выбрал серьезную и очень хорошо проработанную теоретически. Там трудно сказать что-то по-настоящему новое. Ему на это и указали.

Лично я всегда приветствую любую нетривиальную инициативу. Вдруг, действительно получится что-то стоящее.
1
 Аватар для pgb
-508 / 32 / 0
Регистрация: 22.09.2015
Сообщений: 1,232
22.06.2024, 08:42  [ТС]
Цитата Сообщение от Curry Посмотреть сообщение
pgb, воздерживайтесь от оскорблений.
Rius, не провоцируйте его.
Я человеку уже неоднократно говорил чтобы не лез в мои темы с тупыми выпадами, если у гражданина ума не хватает анализировать информацию и отвечать по теме, а только хватает на то чтобы меня оскорблять, высказываясь что я балабол, больной и прочее, это тут значит считается нормальным.. А что я просто назвал субъект амёбой, тем кем он и является, по отношению ко мне и теме разговора, то это вы принимаете за нарушение правил..
Цитата Сообщение от Catstail Посмотреть сообщение
Человек выступил очень претенциозно (одно "учитесь, пока я жив" чего стоит...) Но тему выбрал серьезную и очень хорошо проработанную теоретически. Там трудно сказать что-то по-настоящему новое. Ему на это и указали.
Я не выступаю в отличие от других.. Я занимаюсь своим делом, для реализации своих идей мне нужно решать некие задачи, которые я предлагал делать совместно, искал единомышленников, сейчас просто решил показать как я разрабатываю свои проекты, это лишь малая часть... В этой теме вы можете проследить, то как я прогрессирую и нахожу лучшие решения, то как можно сделать проще, лучше, по другому, что уже существует. Если вы сможете понять смысл создания своей реализации существующих решений, то надеюсь не будет больше тупых вопросов, а зачем это надо, какая польза и прочее..

Итак, я решил переделать парсинг токенов, шаблон будет состоять из конкретного текста для поиска, а для логики и синтаксиса буду использовать символ '~' после которого уже будут идти другие символы, которые будут указывать что нужно находить. Сейчас этим и займусь.
0
Эксперт .NET
 Аватар для Rius
13114 / 7675 / 1674
Регистрация: 25.05.2015
Сообщений: 23,403
Записей в блоге: 14
22.06.2024, 08:55
5.22
Запрещено намеренно вводить других пользователей форума в заблуждение.
С 2017 года можно проследить, как он врёт всё больше и больше (прогрессирует, действительно). Не разобравшись в общепризнанных проектах поливает их г***м, берясь (по причине "ниасилил") переписать всё и вся, но ничего не доведя до ума. Каждый проект бросается даже не на полпути, а раньше, начинается новый с ещё более громкими заявлениями и поливанием всех и вся.
Всё это зафиксировано в его сообщениях на форуме.
0
 Аватар для pgb
-508 / 32 / 0
Регистрация: 22.09.2015
Сообщений: 1,232
22.06.2024, 09:12  [ТС]
Цитата Сообщение от Rius Посмотреть сообщение
С 2017 года можно проследить, как он врёт всё больше и больше (прогрессирует, действительно). Не разобравшись в общепризнанных проектах поливает их г***м, берясь (по причине "ниасилил") переписать всё и вся, но ничего не доведя до ума. Каждый проект бросается даже не на полпути, а раньше, начинается новый с ещё более громкими заявлениями и поливанием всех и вся.
Всё это зафиксировано в его сообщениях на форуме.
Если вы не видели моих завершённых проектов, то это не значит что их нет, это раз. А во вторых ваши больные фантазии(что я ничего не осилил, не умею и не знаю, а вы тут такие мега профи) не имеют ничего общего с реальностью, на деле я реализую всё задуманное, а вы только исходите на говно поливая меня своими испражнениями..

ЗЫ. Собаки лают, караван идёт
0
 Аватар для pgb
-508 / 32 / 0
Регистрация: 22.09.2015
Сообщений: 1,232
22.06.2024, 21:15  [ТС]
Цитата Сообщение от pgb Посмотреть сообщение
я решил переделать парсинг токенов, шаблон будет состоять из конкретного текста для поиска, а для логики и синтаксиса буду использовать символ '~' после которого уже будут идти другие символы, которые будут указывать что нужно находить.
Это было плохое решение. По началу думал так будет проще, но на деле оказалось наоборот..
Оставляю как было с некоторыми правками синтаксиса:

a - любой символ(как .);
b - начало строки, в начале(как^);
c - (CR) возврат каретки(как \r);
d - цифра 0..9(как \d);
e - конец строки, в конце(как $);
f - число с точкой float;
g - true или false;
h - шестнадцатеричное число;
i - число integer;
j - ;
k - ;
l - строчная буква;
m - захваченная подстрока;
n - (NL) новая строка(как \n);
o - или;
p - запомнить текущую позицию;
q - кавычки " или ';
r - количество раз повторов;
s - пробел(как \s);
t - табуляция(как \t);
u - заглавная буква;
v - проверка, vzzzv, где zzz - шаблон;
w - слово;
x - отрицание совпадения;
y - ;
z - спецсимвол;

{text} - конкретный текст;
[zzz] - возможные совпадения(подразумевается "или"), где zzz - шаблон;
(zzz) - захват подстроки, где zzz - шаблон;
* - ноль или более раз повторов;
+ - один или более раз повторов;

Опять же это не окончательный вариант, поэтому код под этот синтаксис не буду сейчас выкладывать, а буду пока тестировать как что будет определятся и тд. Как буду уверен в таком решении, выложу доработанную функцию парсинга токенов выражения, потом буду двигаться дальше, писать функцию поиска в строке по выражению.

ЗЫ. Надо что-то придумать для букв j,k,y какие-то назначения
0
Просто Лис
Эксперт Python
 Аватар для Рыжий Лис
5973 / 3735 / 1099
Регистрация: 17.05.2012
Сообщений: 10,791
Записей в блоге: 9
23.06.2024, 09:59
Вызов panic в коде это прям эпично.

Значения ваших не-регулярок известны на момент компиляции? Тогда можно написать макрос, который в compile-time строит конечный автомат и генерирует функцию. Я почти уверен, что уже существуют подобные библиотеки на расте. Плюсы: должно работать быстро и не тянет runtime зависимостей в проект.

Добавлено через 3 минуты
https://docs.rs/hitori/latest/hitori/

Hitori is generic compile-time regular expressions library. It works by creating series of if-statements and for-loops for each expression.

See code samples along with the traits, impls and structs they expand to in examples.
Добавлено через 7 минут
Хм, пишут, что макрос regex! из стандартной библиотеки тоже complie-time. Аж с 2014 года…
0
 Аватар для pgb
-508 / 32 / 0
Регистрация: 22.09.2015
Сообщений: 1,232
23.06.2024, 10:46  [ТС]
Цитата Сообщение от Рыжий Лис Посмотреть сообщение
Значения ваших не-регулярок известны на момент компиляции?
Первоначально мне нужен свой разбор\парсинг текста для своего языка программирования. В интерпретаторе языка шаблонные выражения изначально будут известны и скомпилированы. А так да есть мысли конечно сделать ещё и модулем для своего же языка чтобы если будет ошибка не паниковать, а выдавать, её через Result или Option например без результата с None

Это всё пока ещё обдумывается. Первоначально надо саму реализацию сделать, доработать всегда можно, что-то улучшить и тд., когда своя реализация-то, в этом и есть самый большой плюс своей реализации в отличие использования сторонней.
0
Просто Лис
Эксперт Python
 Аватар для Рыжий Лис
5973 / 3735 / 1099
Регистрация: 17.05.2012
Сообщений: 10,791
Записей в блоге: 9
23.06.2024, 10:54
Но ведь токенайзер (лексер) пишется проще и ему не очень-то нужны регурярки чтобы разбирать исходный код…

Добавлено через 2 минуты
Во вообще грамматику можно описать, не написав ни строчки кода:

Code
1
2
3
4
5
6
7
8
9
10
PLUS: '+';
MINUS: '-';
STAR: '*';
SLASH: '/';
ID: [a-zA-Z][a-zA-Z0-9_]*;
CONST_INT: [0-9]+;
CONST_STR: '\'' ('\'\'' | ~ ('\''))* '\'';
WS: [ \t\r\n]+ -> skip;
COMMENT1: '(*' .*? '*)' -> skip;
COMMENT2: '{' .*? '}' -> skip;
Добавлено через 2 минуты
ANTLR
2
 Аватар для pgb
-508 / 32 / 0
Регистрация: 22.09.2015
Сообщений: 1,232
23.06.2024, 11:06  [ТС]
Цитата Сообщение от Рыжий Лис Посмотреть сообщение
ANTLR
Для обычных решений - да, для тех кто сам не может написать свою реализацию - да, для языков высокого уровня - да..
Но у меня решение которое отличается от обычных, я делаю по другому и тут нужны другие подходы, я могу написать свою реализацию, и я использую Rust компилируемый язык в машинный код чтобы реализация была как можно чище без кучи сторонних библиотек и прочего.

ЗЫ. Короче я устал всем одно и тоже объяснять. Почему бы вам уже не успокоится и перестать ссылаться на готовые решения, а включать свои мозги для решения каких либо задач?
0
Просто Лис
Эксперт Python
 Аватар для Рыжий Лис
5973 / 3735 / 1099
Регистрация: 17.05.2012
Сообщений: 10,791
Записей в блоге: 9
23.06.2024, 11:10
https://github.com/Kixiron/rust-langdev#parsers
0
 Аватар для pgb
-508 / 32 / 0
Регистрация: 22.09.2015
Сообщений: 1,232
23.06.2024, 11:17  [ТС]
Цитата Сообщение от Рыжий Лис Посмотреть сообщение
и ему не очень-то нужны регурярки
Опять же в реализации того же ANTLR используются те же регулярки вообще-то
Из вашего же примера
[a-zA-Z][a-zA-Z0-9_]*
'\'' ('\'\'' | ~ ('\''))* '\''
[ \t\r\n]+
'(*' .*? '*)'
'{' .*? '}'
Добавлено через 5 минут
Цитата Сообщение от Рыжий Лис Посмотреть сообщение
#parsers
То есть вы думаете я не знаю о существовании модулей на Rust для парсинга?
Так я первым же делом это просканировал, посмотрел что и как, именно поэтому и решил, что они мне не подходят и что хочу сделать по своему.

ЗЫ. Когда же вы успокоитесь-то со своими ссылками на готовые решения, а начнёте включать свой мозг?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
23.06.2024, 11:17
Помогаю со студенческими работами здесь

Объясните, как работает грамматика регулярных выражений ECMAScript
Читаю раздел Alternatives документации по грамматике ECMAScript и не понимаю ни описание механизма работы данной реализации регулярных...

Как найти и заменить подстроку - как есть, без регулярных выражений
Как найти и заменить подстроку - как есть, без регулярных выражений? Уже неделю копаю, но ничего толкового не накопал... Прошу помощи. ...

Как с помощью регулярных выражений можно разделить строку на подстроки?
Всем привет. Как с помощью регулярных выражений можно разделить строку на подстроки? Имеется обычная строка(достаточно большая), необходимо...

Как преобразовать текстовый файл в html с помощью регулярных выражений?
Напишите сценарий, с помощью регулярных выражений преобразующий текстовый файл, заданный аргументом командной строки, в html-файл. ...

Как преобразовать текстовый файл в html с помощью регулярных выражений?
это АНРЕАЛ ребята Напишите сценарий, с помощью регулярных выражений преобразующий текстовый файл, заданный аргументом командной...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Символьное дифференцирование
igorrr37 13.02.2026
/ * Логарифм записывается как: (x-2)log(x^2+2) - означает логарифм (x^2+2) по основанию (x-2). Унарный минус обозначается как ! */ #include <iostream> #include <stack> #include <cctype>. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru