1. C++ / Говнокод #20706

    +319

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    38. 38
    39. 39
    40. 40
    41. 41
    42. 42
    43. 43
    44. 44
    45. 45
    46. 46
    47. 47
    48. 48
    49. 49
    50. 50
    51. 51
    52. 52
    53. 53
    54. 54
    55. 55
    56. 56
    57. 57
    58. 58
    59. 59
    60. 60
    61. 61
    62. 62
    63. 63
    64. 64
    65. 65
    66. 66
    67. 67
    68. 68
    69. 69
    70. 70
    71. 71
    72. 72
    73. 73
    74. 74
    75. 75
    76. 76
    77. 77
    78. 78
    79. 79
    80. 80
    template<typename OpeningBracketRange,
    	typename ClosingBracketRange,
    	typename StopTokenRange,
    	typename CommentBlockRangePairRange,
    	typename RecursiveCommentBlockRangePairRange>
    
    Meta::EnableIf<
    	IsFiniteForwardRange<OpeningBracketRange>::_ &&
    	IsFiniteForwardRange<ClosingBracketRange>::_ &&
    	IsFiniteForwardRange<StopTokenRange>::_ &&
    	IsFiniteForwardRange<CommentBlockRangePairRange>::_ &&
    	IsFiniteForwardRange<RecursiveCommentBlockRangePairRange>::_,
    
    decltype(Meta::Val<R>().Take(0))> ReadRecursiveBlock(int& counter, size_t* ioIndex,
    	OpeningBracketRange openingBracket, ClosingBracketRange closingBracket, StopTokenRange stopToken,
    	CommentBlockRangePairRange commentBlocks, RecursiveCommentBlockRangePairRange recursiveCommentBlocks)
    {
    	R start = me();
    	size_t index = 0;
    	const size_t openingBracketLen = openingBracket.Count();
    	const size_t closingBracketLen = closingBracket.Count();
    	const size_t stopTokenLen = stopToken.Count();
    	while(!me().Empty() && counter!=0)
    	{
    		if(openingBracketLen!=0 && me().StartsWith(openingBracket))
    		{
    			counter++;
    			me().PopFrontExactly(openingBracketLen);
    			index += openingBracketLen;
    			continue;
    		}
    
    		if(closingBracketLen!=0 && me().StartsWith(closingBracket))
    		{
    			counter--;
    			me().PopFrontExactly(closingBracketLen);
    			index += closingBracketLen;
    			continue;
    		}
    
    		if(stopTokenLen!=0 && me().StartsWith(stopToken))
    		{
    			me().PopFrontExactly(stopTokenLen);
    			index += stopTokenLen;
    			break;
    		}
    
    		bool commentFound = false;
    		for(auto& commentBlock: commentBlocks)
    		{
    			commentFound = me().StartsWith(commentBlock.Get<0>());
    			if(!commentFound) continue;
    
    			const size_t commentBlockOpeningLen = commentBlock.Get<0>().Count();
    			const size_t commentBlockClosingLen = commentBlock.Get<1>().Count();
    			me().PopFrontN(commentBlockOpeningLen);
    			index += commentBlockOpeningLen;
    			me().FindAdvance(commentBlock.Get<1>(), &index);
    			me().PopFrontN(commentBlockClosingLen);
    			index += commentBlockClosingLen;
    			break;
    		}
    		if(commentFound) continue;
    
    		for(auto& commentBlock: recursiveCommentBlocks)
    		{
    			commentFound = me().StartsWith(commentBlock.Get<0>());
    			if(!commentFound) continue;
    
    			int commentCounter = 1;
    			ReadRecursiveBlock(commentCounter, &index, commentBlock.Get<0>(), commentBlock.Get<1>(), null, null);
    			break;
    		}
    		if(commentFound) continue;
    
    		me().PopFront();
    	}
    	if(ioIndex!=null) (*ioIndex) += index;
    	return start.Take(index);
    }

    Это мои последние достижения в написании сверх универсального обобщённого кода.
    Начиналось всё с функции, которая парсила блок кода до закрывающей фигурной скобки, учитывая встречающиеся открывающие скобки. Затем появилась поддержка комментариев и строк. Позже я решил, что нечего привязываться к какому-то конкретному языку, ведь можно же таким же образом парсить другой язык, где вместо скобок begin end и комментарии по-другому оформляются.
    А потом я подумал, зачем вообще привязывать типы параметров к строкам и массивам строк? И почему код, который парсится, вообще должен быть строкой, хранящейся в памяти непрерывно? В итоге мои размышления привели к такой реализации, которая способна парсить всё подряд, в том числе и связные списки, причём необязательно состоящие из символов. При этом открывающуюся скобку можно передать связным списком, закрывающуюся - массивом, а блоки комментариев передавать как массивом кортежей, так и хеш-таблицей.

    При этом эта функция относится к классу примеси и наследованием её можно подмешать к любому классу, имеющему нужные методы.

    Запостил: gammaker, 15 Августа 2016

    Комментарии (39) RSS

    • А можно несколько простых примеров использования для праздно шатающихся читателей?
      Иначе выходит как у того математика, который исписал 1000+ листов новой математики. Вроде бы и полезно, но прочитает целиком не каждый.
      Ответить
      • StringView code = "int main() {"
                "/*{eegregwG{fwer43r4*/"
                "printf(\"some smiles :}    :-{\");"
                "if(0) {}"
                "return 0;"
            "}"
            " some shit at the end";
        StringView readBegin = code.ReadUntilAdvance("/*"_v);
        assert(readBegin == "int main() {");
        assert(code == "/*{eegregwG{fwer43r4*/printf(\"some smiles :}    :-{\");if(0) {}return 0;} some shit at the end");
        int counter=1; //Начинаем с вложенности 1
        const Tuple<StringView, StringView> comments[3] = {{"/*", "*/"}, {"//", "\n"}, {"\"", "\""}};
        StringView readBlock = code.ReadRecursiveBlock(counter, "{"_v, "}"_v, null, AsRange(comments), null);
        assert(counter == 0); //Соответствующая закрывающая фигурная скобка была найдена
        assert(readBlock == "/*{eegregwG{fwer43r4*/printf(\"some smiles :}    :-{\");if(0) {} return 0;}");
        assert(code == " some shit at the end");

        Это такой самый нормальный пример. А ненормальные типа парсинга списка структур вместо массива символов я пока ещё и сам не придумал.
        А ещё в моей реализации поддержки экранирования строк нет. Писал прямо здесь, на компилируемость не тестировал.
        Ответить
        • когда уж в кресты завезут констекспрес стринг, в котором можно будет запихать код и скомпилить в компилтайме?
          Ответить
      • показать все, что скрытоНе жабаскриптерского ума дело
        Ответить
    • код на основе чрезмерно обобщенного кода иногда писать сложнее чем с нуля реализовывать частные случаи.
      Ответить
      • Ключевое слово "иногда". Я делаю всё, чтобы это был не мой случай. Единственная проблема, которую ввёл обобщённый код - это то, что теперь все типы нужно указать точно и явно. Никакие неявные касты, к которым я привык, теперь не работают. А так как строковые литералы и initializer_list не реализуют нужный интерфейс, их нельзя передавать напрямую, а надо явно приводить их к нужному типу.
        Ответить
      • Самое смешное, что обобщённый код в области парсинга -- это парсер комбинаторы (parsec, spirit, тысячи их). А тут обобщением и не пахнет, зато к тематике сайта подходит.
        Ответить
        • Ну тут не совсем область парсинга. Я обобщаю строки, массивы, списки и потоки. Я просто пихаю в свои диапазоны все те алгоритмы, которые раньше писал для частных случаев, а то и по нескольку раз, только в более общем виде. А ставшие ненужными уже написанные частные случаи выкидываю. Там и поиск поддиапазона в диапазоне, который работает как с массивами, так и со строками, потом замена одних элементов другими, всякие там Map\Reduce и так далее. Почти все алгоритмы, которые есть в STL и многие алгоритмы, которых там нет. Среди них оказался и этот алгоритм, который я использовал в своём текстовом десериализаторе, чтобы пропустить десериализацию несуществующих полей или пропустить блок, содержащий ошибку. Я обнаружил, что он не содержит ничего такого специфичного для строк - никаких специальных манипуляций с символами, не требует произвольного доступа. А так как у меня все алгоритмы теперь подразделяются по требованиям к диапазонам, то он попал в концепт FiniteForwardRange, к которому относятся почти все диапазоны и контейнеры. Разве что файловые потоки не входят сюда, потому что позиция в них глобальна и её нельзя хранить в объекте диапазона.
          Ответить
          • https://dev.by/lenta/main/intervyu-s-krisom-kasperski-aka-mysch-h
            — Как я понял, твой успех был отчасти в том, что все пытались найти общее универсальное решение и впоследствии увязали в нарастающей сложности. Ты же решил узкоспециализированную задачу, зато смог это сделать эффективно и быстро. Немного отвлекаясь от основной темы, здесь мы снова возвращаемся к любимому тобой спору вокруг назначения языков C и C++.

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

            Одну текущую задачу сначала показали «плюсовику», спросив, сколько займёт её решение. Он сказал: «Здесь нужно писать могучий движок. Короче говоря, это проект на полгода». Его коллега-«сишник» поинтересовался: «А зачем?» Ведь поставленная задача укладывается в сотню строк кода! Ответ был ошеломляющим: «Ну и что, мы так и будем по сотне строк кода писать для решения частных задач, каждый раз, как они возникают? Нетушки, задачи надо решать раз и навсегда!».

            По моему глубокому личному убеждению, проблемы нужно решать по мере их возникновения. Писать программы на вырост с избыточным универсализмом нужно лишь очень хорошо предварительно подумав, ибо это из серии «Почему сегодня не делают корабли, летающие к звёздам?» Ответ прост: потому что корабль, построенный завтра, прибудет быстрее, а корабль, построенный послезавтра, еще быстрее. И их обоих обгонит корабль, построенный лет через пятьдесят, но когда он вернётся обратно, то обнаружит, что у человечества совсем другие проблемы».
            Ответить
        • это парсер кобенаторы
          Ответить
      • Самый обобщенный код это программист нейросеть, которую можно любой хуйне обучить, хоть сортировке, хоть игре в шахматы. Программист есть лишь хардварно-биологическая реализация нейросети
        Ответить
        • показать все, что скрытоПопизди мне еще
          Ответить
        • вот пусть и учится программировать на крестах
          Ответить
          • Нейросети похуй на чем программировать, можно и на брейнфаке даже.
            Ответить
            • А как же пирфоманс?
              Ответить
            • мне похер на чем могут. Я хочу чтоб на крестах
              Ответить
              • Скорее всего нейросеть выматерится трехэтажным матом на кресты и напишет код с одной функцией и целиком на ассемблерных вставках
                Ответить
                • Чтоб такого не было, нужно обучать на книгах Мейерса и Саттера. Александреску не давать!
                  Ответить
                • пусть матерится сколько влезет. Мне надо - пусть ебошит
                  Ответить
          • Каждые 3 года нейросеть будет ох#&вать от нового стандарта и переучиваться.
            ебаные человеки, что вы опять понавыдумывали
            Ответить
            • Собираются же после 20го на 2 года перейти.
              Ответить
              • В 30х будет раз в две недели?
                Каждая новая версия хрома будет написана на новом C++.
                Ответить
                • В 30-х не будет Хрома. Будет принципиально новый веб-браузер, лишённый фатальных недостатков. Да и HTTP тоже не будет, будет новый протокол, лишённый фатальных недостатков. И HTML поменяют на новый язык, как Вы уже догадываетесь, лишённый фатальных недостатков.
                  Ответить
                  • показать все, что скрытоВ 30 не будет необходимости в браузерах. Люди станут напрямую обмениваться мыслями, а вирусы будут писаться на языках нейролингвистического программирования, и последствия от их атак будут куда более плачевными..
                    Ответить
                    • Вот до чего Лига без Интернета доводит.
                      Ответить
                    • Вот специально найду потом этот коммент на говнокоде в 2030 и отвечу на него
                      Ответить
                      • Не забудь перевести деньги на домен стрит страйкеру
                        Ответить
      • показать все, что скрытоДа, говнгкодить квадратные лесапеды проще,, чем читать мануал по библиотеке
        Ответить
        • зависит от библиотеки. Если используя либу решение получится лучше и быстрее, а код - красивее, вопросов нет. А если что с либой что без неё код примерно одинаковый по сложности, объему и стабильности, то лучше написать свой родной квадратный велосипед, чем пытаться заказать квадратный велосипед на фабрике треугольных
          Ответить
    • Да уж, этот код апвот заслужил.
      Ответить
    • показать все, что скрытоКакой багор )))
      Ответить
    • Угадал автора с 8 строчки
      Ответить
    • показать все, что скрытоЯ анальный учитель. Я АНАЛЬНЫЙ УЧИТЕЛЬ. Я буду анальным учителем!
      Я учитель! Я анальный учитель! Я БУДУ АНАЛЬНЫМ УЧИТЕЛЕМ!!!!
      Ответить

    Добавить комментарий