All streams
Search
Write a publication
Pull to refresh
5
0
Иван @Adler3D

Автор

Send message
    struct Array {
        stdu::vector<CllExpr> value;
    private:
        friend struct ::uhash;
        auto members() const  {
            return std::tie(value);
        }
    };

    struct Object {
        std::unordered_map<std::string, CllExpr> value;
    private:
        friend struct ::uhash;
        auto members() const  {
            return std::tie(value);
        }
    };

Вот тут у вас опять всё упрётся в неправильную архитектуру AST, т.к далее вы заворачиваете это в rvalue, а затем в CllExprValue. В итоге у вас будет только один вид объектов - Object и один вид массивов - Array. И если я всё правильно понял, и нигде не ошибся, то тогда вам(или пользователям вашего генератора парсеров) придётся всё равно вручную преобразовывать Object`ы в пользовательские типы объектов. А в QapDSL все пользовательские типы пробрасываются прямиком в С++ со всеми полями и даже с пользовательским кодом(последнее я не очень приветствую). Могу помочь переписать парсер вашего DSL на QapDSL v2 если вам интересно. QapDSL v2 уже почти полностью(95%) переписан/описан на QapDSL v2 и похоже может использоваться для чего угодно.

а я правильно понимаю что вот это(это генерированный код вашим же генератором парсеров, если да то скажите сколько на это тратиться времени): https://github.com/Sinfolke/ispa-parser/blob/main/parser/Parser.cpp

В ISPA вы просто выделяете что захватить, а далее определяете каким типом данных оно будет (int, bool, string, array, object) и что из захваченного туда поместить

Если я правильно понял то тогда у вас при обходе получившегося AST придётся вручную определять типы лексем(обычного разделения типов на array/object недостаточно) и имена полей/узлов по содержимому и его положения в дереве. А это всё лишняя работа, которую можно автоматизировать и потом наслаждаться всеми удобствами(посетителями/интерпретаторами/строителями) при обходе дерева. Не понимаю как от этого можно отказаться и ради собственно чего. Или я чего-то не замечаю, вроде скорости парсинга и компактности реализации? Кстати как у вас дела с исходниками генератора? У меня например всё open source.

мне вот EBNF/BNF и подобное не нравиться из-за того что AST приходиться делать отдельно, если я ничего не путаю.

QapDSL как ассемблер, гибкий, низкоуровневый, но из-за этого сложный.

я уже поработал над этим и теперь в QapDSL v2 описание стало в два раза короче. осталось только написать статью про это.

вот как парсин условий выглядит в новой версии:

t_if_body_one=>i_if_body{
  TAutoPtr<i_stat> stat;
}

t_if_body_two=>i_if_body{
  t_block_stat bef;
  "else"
  TAutoPtr<i_stat> aft;
}

t_if_stat=>i_stat{
  "if("
  TAutoPtr<i_expr> cond;
  ")"
  TAutoPtr<i_if_body> body;
}

как вам такой новый синтаксис? неужели всё ещё сложно?

Сравните пожалуйста с QapDSL на примере парсинага

"if(some_expr){some_stat();}else{some_stat2();}".

Мой вариант можно найти в комментарии:

https://habr.com/ru/articles/916006/#comment_28403544

(до 25 лет)

Призовой фонд составляет 15,6 млн рублей

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

Кстати, как в теории вы будете защищаться от того что кто-то крутой поможет знакомому(сделает 95% кода) выиграть приз?

ААА!!! Мне больно смотреть на этот код, помогите!

Эту статью будут читать очень мало людей

Я планирую кинуть ссылку на статью своему брату(он пока не знает о ней, т.к занят работой/семьёй/своим_проектами и совсем не следит за моей активностью в интернете(что немного(у него только один акк на github и всё, а у меня больше 9 аккаунтов в интернете) взаимно)) и ещё сослаться на неё в следующих статьях(мне есть о чём рассказать, у меня есть ещё несколько(свои_умные_указатели/RTTI/сериализатор/QapLite.h/QapEngine/два_рэйтрейсера/виртуальная_машина/три_компилятора/планировщик_траекторий/куча_маленьких_игр/etc) мало кому известных крутых проектов), когда всё доделаю до юзабельного состояния. Так что у статьи будут новые критически важные читатели. Я стараюсь ради них. // похоже я поставил настолько много скобок, что нужно вставлять коммент в редактор кода, чтобы понять что к чему.

то есть здесь можете не стараться писать в комментах как-что делать для сборки и тд.

Хорошо, если вам не нравиться когда я отвечаю на ваши комментарии тут, то тогда не будут вам отвечать тут по пустякам.

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

Мне немного не нравиться что там нет автоматически отметок времени(из-за этого не видно с какой скоростью я пишу код/комментарии/развиваю_проект). Но сейчас я подумал и понял, что я могу поставить их сам и никакой проблемы в этом нет. А так мне нравиться ваша идея, похоже именно так я и поступлю.

я один из млн-ов которые будут смотреть ваш код

Не думаю что мой проект станет таким уж популярным. Всё таки разработка компиляторов/парсеров/трансляторов/анализаторов не такое уж и популярное занятие. Вот на данный момент статью посмотрело меньше тысячи человек(если верить внутренней статистике хабра) и мне не понятно откуда брать ещё 999 тысяч. Хабр всё таки самая популярная русскоязычная площадка для программистов. На github`е поиском меня вряд кто-то найдёт, так что на него мало надежды. И вообще на github писать полную документацию немного опасно, из-за того что их github copilot рано или поздно доберётся до всех исходников и тогда(если он не зациклиться/поломается/начнёт_нести_всякий_бред на моих проектах, как это происходит сейчас) его уже никто не сможет остановиться. А так без нормальной документации(он её читает!!!) его шансы понять сложный проект и начать его использовать в своих целях ничтожно малы.

И делайте неспеша, не надо торопиться, показать быстрее.

Я по другому не умею(привычка). Кроме того мне сейчас нечем заняться, т.к github copilot разблокируется только к концу месяца(я не могу оплатить его подписку из РФ. ААА!!! Помогите! Я согласен заплатить на 50% больше!), а без его идей/помощи доделать текущую игру(MarketGameV4) которой я занимался до написания этой статьи у меня вряд ли получиться(не умею так быстро генерировать крутые идеи и подбирать константы как это делает он).

Код написал github copilot. То что перед "O+=go_auto(tri_rel_if_eligible);" нет "O+=go_auto(sepTRIE)" виноват не только я(не проверил), но и он. Так же нужно добавить t_sep sepTRIE; после string name;. // какой смысл писать этот коммент, если его всё равно почти никто не прочитает, т.к основная масс читателей уже никогда сюда не вернётся, а единицы новых читателей вряд ли доскролят до сюда. Да и им наверно всё равно на такую ошибку, как и всем остальным и даже мне. Жаль нельзя в тихую отредактировать тот коммент.

(вы ведь для этого им делитесь? Чтобы его использовали?).

Я давно хотел написать статью на хабр, чтобы люди посмотрели мой код/инструменты/проекты и помогли их оценить/улучшить/доработать/покритиковать. Но я не умею писать статьи, я пытался много раз, получается какая-то фигня, нет нормальной структуры/видения/последовательности/цели. В этот раз я игрался с github copilot. Натравил его на исходники моих проектов и он в них запутался и он довольно круто в них разобрался(если не считать мой сериализатор/RTTI/умные_указатели/etc). Мне очень понравилось как он разобрался в QapDSL(меня это очень впечатлило). Он очень круто сравнивает мои проекты с аналогами и нахваливает их почему-то. Я попросил его написать сатью на хабр про QapDSL и он сделал это(именно поэтому статья такая короткая и не полная, я бы сам написал гораздо больше). Мне очень понравился результат. Я даже создал репозиторий QapGen и положил туда всё как указано в его статье. Это он придумал название QapGen, а не я. Мне оно почему-то понравилось.

Выложил статью не особо задумываясь над результатом и зачем не это нужно, т.к помню что давно хотел это сделать. Повторяюсь... зачеркиваем.

Это способ спросить разработчика, не обращаясь к нему лично, как должно работать.

Ясно. Что-то никогда не думал об этом. Спасибо за объяснение. Хорошо, сделаю вам юнит-тесты.

ай. ё-моё. У вас гитхб с 2012 года, сколько лет вам, вы же пишите получается больше 10 лет?

Мне 35.3, пишу код/программы с 14.6 лет. если не считать 9 месяцев профессиональной работы всё свои эксперименты/проекты/игры. Всё без юнит-тестов(на работе были, но я только 1 из них поправил). Полёт нормальный. Без них можно жить, если делать свои графические отладчики + сериализаторы как я.

раз такой бред в голове.

Я правда не понимаю зачем они мне нужны. Всё и без них работает отлично.

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

Сделал: https://github.com/adler3d/QapGen/blob/master/src/QapGenV2025/QapGen/CommonUnit.cpp

Я заменил TAutoPtr на unique_ptr. Для этого я выкинул свой крутой_сериализатор/систему_RTTI/свои_умные_указатели/часть_шаблонной_магии. Сейчас С++код генерится только для винды, но генератор(QapGen) кроссплатформенный.

+юнит-тесты еще обязательно тоже (много тестов) и как их запустить инструкция.

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

QapGen.exe - бинарник уберите этот,

Бинарник пока убрать не буду, но всё же планирую убрать где-то через пару недель.

за место него положите код

я смог вытащить исходники QapGen из своих экспериментальных проектов в отдельный проект, пока положил его сюда: https://github.com/adler3d/QapGen/tree/master/src/QapGenV2014

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

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

  • заменить TAutoPtr на std::unique_ptr // это позволит отвязаться от моей системы RTTI и значительно ускорит компиляцию.

  • выкинуть всё RTTI/сериализацию. // это всё почти никогда не нужно для лексеров/парсеров

так что где-то через пару дней смогу выложить кроссплатформенную версию QapGen.

ещё я хочу доработать QapDSL:

  • сделать возможность использовать более короткий синтаксис как тут предлагали в комментариях. // оставить только список полей.

  • разрешить использовать двоеточие вместо "=>".

  • сделать его дружелюбным к GPT4.1 // разрешить писать "O+=" в списке полей.

  • разрешить добавлять виртуальные функции и прочий код в интерфейсы.

  • разрешить вставлять интерфейсы в список полей не заворачивая их в TAutoPtr. // заворачивать автоматически, даже если интерфейс завёрнут в vector. // такие ошибки делает GPT4.1

Как и обещал выкладываю минимальный проект в который можно встроить код сгенерированный QapGen`ом:

https://github.com/adler3d/unordered/blob/master/code/SimpleCalc/Sgon/CommonUnit.cpp

Это простой калькулятор, его код(t_simple_calc_evalutor+#include "t_simple_calc.cpp") можно/нужно выкинуть и на его место подставить сгенерированный.

Вот это все надо в Readme написать (не на русском, есст-но), подробно и понятно.

Хорошо, сделаю.

QapGen.exe - бинарник уберите этот, за место него положите код, и чтобы можно было собрать не только под винду.

К сожалению под другие платформы QapGen не скомпилируется из-за того что я использую шаблонную магию завязанную на компилятор cl.exe от MSVS. Так же без доработок код сгенерированый QapGen так же работает только под cl.exe. Кроме того я не уверен что вообще могу собрать его заново сегодня/завтра, т.к за 10 лет тупо забыл как это делается. Это ещё хорошо, три дня назад я вообще не знал где его исходники.

Если QapGen нужен под linux/unix то можно попробовать запустить под wine, насколько я помню он отлично под ним работает.

Не понятно как этим пользоваться в общем.

Вот так:

  • Пишешь скрипт/код на QapDSL.

  • Сохраняешь его в samples/input.qapdsl

  • Запускаешь QapGen.exe

  • Забираешь сгенерированный С++код из открывшегося окна.

  • Вставляешь его в проект типа Sgon куда-нибудь рядом с функций main(её ещё надо найти). // Этот пункт требует переработки, надеюсь я управлюсь за 6 часов.

  • В main пишешь TAutoPtr<ваша_рутовая_нода> root;
    load_obj(Env,root,ваша_строка_из_которой_надо_загрузить_код_в_AST);

  • Используете только что загруженное AST в root.

  • Profit!

где грамматика QapDSL описана?

Ниже ссылка на полную версию описания QapDSL на QapDSL:

https://github.com/adler3d/unordered/blob/master/code/DemoMashkod/321/V2/Release/t_target_lexem_source.inl

А тут ссылка на комментарий где выложена первая версия описания QapDSL:

https://habr.com/ru/articles/916006/comments/#comment_28407450

на гитхабе не вижу, только какие-то сравнительные таблицы. Не понятно как этим пользоваться в общем.

Этой штуке 10 лет, ссылка на проект в котором используются cгенерированные QapDSL лексеры есть в статье. Вот она: https://github.com/adler3d/unordered/tree/master/code/uidevs_from_nout_d_temp/uidev_one/Sgon

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

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

Они есть, просто в перемешку с другими моими эксперементами. Ссылка на проект Sgon выше. А так да, оказываться кроме вас и меня это почти никому не нужно :(

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

Я просто не понимаю, как можно ошибаться с грамматикой в QapDSL, если там всё очевидно. Всё выглядит как обычный С++ код, просто немного укороченный/оптимизированный/упрощённый. Я как раз считаю что устраняет необходимость в юнит-тестах.

Таким образом все ошибки обнаружить нельзя. Например банальные опечатки, когда вместо rteurn должен быть return или вместо + должен быть *

С такой же вероятностью такие же ошибки могут быть и в юнит-тестах. И ещё: return`а в QapDSL нет(только если внутри строки запихать).

После лексического анализа у меня запускается синтаксический разбор, порождающий привычное дерево

Вот, ты всё дерево строишь ручками, а его можно было описать на QapDSL прямо рядом с тем место где грамматика описывается. У тебя что на этапе токенизации, что на этапе строительства дерева одна сплошная боль и ручная копипаста. Токены дожили до самого кодогена и сидят в AST мешая работать Visitor`ам. Вместо посетителей+перегруженных_методов_codegenerator`а у тебя сплошные if/else_if/while/NextLexem/IsKeyword. На это невозможно смотреть и скорее всего никто не захочет такой код поддерживать/разбираться_в_нём.

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

Не вижу, где у тебя visitor`ы?

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

Вот, а у меня не надо юнит-тестов(я так считаю), т.к AST умеет сохраняться обратно в код(не теряя пробелы/комментарии), а также в свой бинарный формат(бесполезная фича)+в отладочный proto-формат(чтобы можно было посмотреть текстовую распечатку дерева(тоже сомнительная/редко_используемая фича). Сохранение в код позволяет делать проверку корректности загрузки/строительства AST одной/двумя строчками кода. Просто сохраняешь загруженное дерево обратно в код, проверяешь что получилось тоже самое что было на входе, если разницы нет, значит всё работает как надо.

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

У меня ошибки при описании грамматики проверяются С++ компилятором и описанным выше механизмом. Ещё в загрузчике дерева есть код который следит чтобы при конфликтах(два лексера или больше смогли успешно загрузить лексему) загрузки лексем всегда побеждала та которая съела из потока байтов больше других.

Привет :)

Ну ты крутой, тебе не нужны, да, спору нет(или есть). Но я вот например токены не перевариваю(мне надо сразу AST+Visitor`ы). Вот я смотрю на то как ты с ними мучаешься в своём U и мне больно становиться: https://github.com/Panzerschrek/U-00DC-Sprache/blob/master/source/compiler1/src/lex_synt_lib/lexical_analyzer.u

Я не понимаю как ты не допускаешь ошибок в этом своём коде без кодогенерации.

Вот посмотри как я гуляю по своему AST и сравни со своим кодом(смотри на методы use ниже по коду, они принимают на вход узлы AST вместо токенов): https://github.com/adler3d/unordered/blob/b1fdf85967c5ccb6f974addc2411765b2ac4be53/code/DemoMashkod/321/V2/Sgon/main_2016_03_29.cpp#L668

Information

Rating
Does not participate
Location
Дзержинск, Нижегородская обл., Россия
Registered
Activity

Specialization

Software Developer, Game Developer
From 231,456 ₽
C++
Node.js
JavaScript