LINUX.ORG.RU

Rust vs C

 ,


3

7

Я Rust не знаю.
Допустим решил я написать быстрый лексер (разбиватель токенов),как я делаю это в Си:

typedef struct {
    const char* text;
    size_t      text_len;
    size_t      text_pos;

    const char* token;
    size_t      token_len;
} lexer_t;
 
void lexer_next_token(lexer_t* lexer);

И я могу получить все токены без выделения памяти,я просто иду по тексту и ставлю lexer_t.token в начало токена, и в token_t.token_len записываю длинну токена.А в расте как сделать подобную вещь?Тоже без выделения памяти естественно (ну кроме стека,где выделяется код возврата и 2 size_t для функии next_token).Верней можно ли сделать такое в расте?

Ответ на: комментарий от khrundel

Да пофиг, это абстрактный пример. Пусть чувак оформит свое виденье lexer_next_token и сделаю аналог нормально.

AntonyRF ★★★ ()
Ответ на: комментарий от AntonyRF

Я на расте не понимаю как это написать,поэтому и вопрос тут задал)Не со зла на С пишу..))

linuhs_user ()
Ответ на: комментарий от anonymous

https://linux.die.net/man/3/strtok

Он всё равно не поймёт, что это не лексер, хоть у него и вариант без записи '\0' в исходный буфер, чем strtok иногда плоха, например для mmap на файл.

vodz ★★★★★ ()
Ответ на: комментарий от anonymous

Щас аргументированно отвечу)подожди,я сонный не могу понять баг..))

linuhs_user ()
Ответ на: комментарий от linuhs_user

Ох, ну придётся подождать, а то тут параллельно ещё работать заставляют =)

AntonyRF ★★★ ()
Ответ на: комментарий от vodz

Это ты не можешь понять что можно добавить различные параметры к токену.

linuhs_user ()
Ответ на: комментарий от pftBest

Вот, смотри, написал твой парсер
extern crate nom;

читер ;)

anonymous ()
Ответ на: комментарий от pftBest

А сделаешь с пропуском пробелов и чтоб захватывал только слова A-Za-z и запятые?Сравнить с Си надо)

linuhs_user ()
Ответ на: комментарий от linuhs_user

Ну требования разные бывают. В таком виде как сейчас парсер работает с юникод строками, и понимает и русские и китайские буквы, можешь убедится написав «Привет Мир» вместо «Hello world» и оно успешно его распарсит.

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

pftBest ★★★★ ()
Ответ на: комментарий от pftBest

Я реализую юникоды)Хотя можно проще,пусть разбивает все на токены,пробелы это разделители которые не сохраняются,а запятые тоже разделители но сохраняются

linuhs_user ()
Ответ на: комментарий от pftBest

Вообще-то utf-8 как раз придумали для того, чтобы не приставали с вопросами как работать: с байтами или символами. Ничего же не меняется. Какая разница в «привет» и в «п©я─п╦п╡п╣я┌» и тем более в пробельных символах? Нате вам многобайтные разнобайтодлинные строки и мучайтесь с вашими папуасскими языками сами, если вам нужны токены «еще» == «ещё»

vodz ★★★★★ ()

Пц вы срач развели. Ну хочет человек сперва разбить текст на разумно выглядящие токены а потом ихуже парсить не морочась от тип символов. Так це умно.

Мое возражение только в том, что надо просто сделать вектор со смещениями. Т.е вектор из пар (начало, конец)

ckotinko ☆☆☆ ()
Ответ на: комментарий от vodz

Так фишка в том что раст проверяет корректность всех этих многобайтных символов когда преобразует из байт в строку, чтобы все по стандарту было.

pftBest ★★★★ ()
Ответ на: комментарий от ckotinko

Ну хочет человек сперва разбить текст

Да наздоровье. Но у нас свобода слова. Другой человек хочет ему объяснить, что это не лексер и вообще эталонное ненужно, ибо бесполезное пожирание памяти.

Так це умно.

Вы сами то поняли что сказали? Умно потому что человек хочет?! Ну ахренеть доказательство!

vodz ★★★★★ ()
Ответ на: комментарий от vodz

Ну ахренеть доказательство!

Выпий яду уже)Я тебя просил показать пример,а ты «типо не увидел».Слишком толсто

linuhs_user ()
Ответ на: комментарий от linuhs_user

Так хорошо, а как мерять будешь? Читать текст из файла? Давай сразу определимся по формату, мне самому интересно стало насколько юникод повлияет на скорость.

pftBest ★★★★ ()
Ответ на: комментарий от pftBest

Какое нибудь предложение размножить на 10 Мб,и пусть из файла читает.А мерять через time только умею))Как правильно?

linuhs_user ()
Ответ на: комментарий от ckotinko

Мое возражение только в том, что надо просто сделать вектор со смещениями. Т.е вектор из пар (начало, конец)

Зачем хранить смещение, если можно сразу хранить указатель? Потом же удобней будет работать.

anonymous ()
Ответ на: комментарий от vodz

Всегда интересовал вопрос, какой диагноз у взрослых людей, прибегающих к такому детсадовскому «аргументу».

А какой диагноз у тех, кто уходит от сути вопроса и разговаривает сам с собой? Чего вы прицепились к лексеру? Перечитайте еще раз вопрос ТСа и спрячьте свой снобизм как можно глубже.

andreyu ★★★★★ ()
Ответ на: комментарий от andreyu

++

vodz, ты забил ветку своим выпендрежем «я знаю как пишут сканеры!», а на вопрос ТС не ответил.

anonymous ()
Ответ на: комментарий от linuhs_user

Вот, сделал пример который просто считает количество токенов первого и второго типа и пропускает пробелы. Его можно взять за базу чтобы начать оптимизировать.

https://play.rust-lang.org/?gist=644e31bafffef563f46d587728ecbed8&version...

pftBest ★★★★ ()
Последнее исправление: pftBest (всего исправлений: 1)
Ответ на: комментарий от vodz

Да, это не лексер. я с вами согласен.

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

бесполезное пожирание памяти

Не жидитесь. Ну неужели вы думаете, что в нормальной программе может быть файл размером в хотя бы полмегабайта? это уже необслуживаемый код. Подход с вектором дает нам максимум 5 мегабайт памяти для мегабайтного файла при условии что там все токены по одному символу и пробелов нет. У вас нет пяти мегабайт? Выкиньте свой 486й и купите хотя бы пентиум-2.

ckotinko ☆☆☆ ()
Ответ на: комментарий от linuhs_user

заведи сперва вектор из пар (size_t, size_t). можно даже (uint,uint). Не думаю что тебе файл в 2 гигабайта встретится. Просто иди по файлу и выделяй последовательности явно напоминающие токены. Даже не парсь их. Составь список возможных токенов и типов символов входящих в них. Можно regex написать, или просто finite state machine с strchr для определения попадания в допустимый набор использовать. Если язык допускает разночтения уже на этом уровне - выкинь его нах, настрадаешься потом. Этот язык уже не распарсиваемый. Для уникода в utf8 есть GLib с набором функций для хождения по тексту.

https://developer.gnome.org/glib/stable/glib-Unicode-Manipulation.html

Тебе сейчас местные алени расскажут «как надо», хотя сами они парсеров никогда не писали. Они просто «художники, они так видят».

ckotinko ☆☆☆ ()
Ответ на: комментарий от pftBest
cargo build --release
...
time ./target/release/speed-lexer
real	0m0,329s
user	0m0,329s
sys	0m0,000s

vs

gcc my.c
...
time ./a.out
real	0m0,273s
user	0m0,256s
sys	0m0,017s

https://pastebin.com/B2DuVjcE
Сейчас попробую в char32_t транслировать

linuhs_user ()
Ответ на: комментарий от linuhs_user

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

сделал два - прошел по токенам, опознал скобки, keywords, выделил scopeы.

если у тебя редактор, то ты уже можешь например по вводу { или } понимать, что перепарсивать надо за пределами текущего scope(но делать это надо по таймеру - через 3-5 секунд после того, как кончили клацать). а пока чел пишет - только в пределах scope.

сделал три - выделил выражения. может что-то подсветил.

быстрый лексер на практике во-первых не нужен - последовательное приближение может быть быстрее самого алгоритмически-быстрого лексера просто потому что оно дружелюбнее к кэшу. во-вторых, а зачем? +-15% от времени компиляции погоды не сделают а в IDE как я выше писал, надо перепарсивать минимум возможного. В идеале скобки {} (для С например) должны быть вообще принудительными и нередактируемыми. Я вот так и сделал, например.

ckotinko ☆☆☆ ()
Ответ на: комментарий от ckotinko

А я обычно парсю лиспы да хтмль)Мне этого хватает,пока не занимался чем то сложным

linuhs_user ()
Ответ на: комментарий от pftBest

Почему нет? Ты знаешь вообще зачем он там?

Это неважно зачем он там - важно то, что он там есть. Как же безопасность?

anonymous ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.