Pull to refresh

Comments 27

Вы не описали каким образом происходит парсинг. В предыдущем вашем посте я успел заметить что вы используете регулярные выражения. Неплохо было бы узнать больше технических деталей: как парсите, в какие структуры и для чего загоняете, каким образом поддерживается css dom mapping (если он поддерживается) и т.д.
Проект на гитхабе я просмотрел, но файлов там много и в точности понять как оно работает проблематично.
Парсер — традиционный LL(1). Собственно, естественный выбор при написании парсера вручную. Вручную вычислять таблицы LR вряд ли практично. :)

Для информации: в Хроме используется LR. Генерируется на основе грамматик.

Регулярные выражения используются только для преобразования исходного кода C++ в код C#. Это сделано в надежде, что метод позволит относительно безболезненно обновлять исходники. Насколько надежда оправдается — время покажет.
Ясно :)
А вот у вас есть метод CssLoader.ParseSheet(...) который внутри вызывает CssParser.ParseSheet(...) — я не могу найти этого метода в классе CssParser. Куда смотреть?
На Гитхабе гулять по проекту будет не очень удобно, так как многие файлы partial, иногда части оказываются в разных папках. Нужный вам кусок CssParser лежит в Style/Original/nsCSSParser.conv.cs (в */Original/ лежат исходники на C++, преобразования T4 и результаты их работы). Разные имена файлов — это последствия рефакторинга имён классов: решарпер не переименовывает сгенерированные файлы, а классы я переименовал не все (только публичные). Наверное, стоит причесать.
Возможно, Вам понравится либа Sprache для парсинга.
В одном своем проекте я заменил самописный парсер на парсер с помощью этой либы.
В итоге код уменьшился раз в 7-8.
Интересная штуковина, гляну.

На самом деле мне бы парсер C++, написанный на C#, не повредил… Или можно сишный препроцессор хотя бы прикрутить, а то код меня местами реально напрягает (только препроцессор работает с сишными лексемами, что не позволяет написать препроцессор в десять строчек).
Не знаю, насколько оправданно описывать работу парсера, потому что я его не писал, а портировал практически один-в-один из Firefox. Кода там очень и очень дофига. Если хотите изучить подробнее, то можете начать с лексера [ns]CssScanner и парсера [ns]CssParser — в них содержится основная логика библиотеки. Всё остальное — это в основном просто классы с полями и некоторыми вспомогательными методами.

Некоторые вещи с C++ не очень портируются, например, union я либо заменял на object и добавлял свойства, кастующие к нужному типу; либо просто добавлял все поля как есть; указатели на поля приходилось заменять свойствами, в крайних случаях делегатами. Было несколько подобных неприятных мест, которые приходилось переписывать с нуля, но остальной код преобразовывался достаточно прямолинейно — шарп и плюсы очень родственны, а арифметики на указателях и прочих неинкапуслированных дикостей было достаточно мало. Очень много мороки доставило преобразование указателей, указателей на указателей, ссылок, ссылок на указателей и прочих комбинаций к ref/out и массивам — много где не сразу очевидно, что требуется.

каким образом поддерживается css dom mapping

Что вы имеете в виду? Получение стиля по описанию положения элемента HTML в иерархии элементов? Этого нет.

Возможно, добавлю. Надо будет обсудить библиотеку с автором CsQuery (порт jQuery на .NET). Он что-то там писал про отсутствие фич, связанных с CSS.
У меня свой проект по парсингу css на гитхабе. Я использовал lex/yacc порт (ply) на python для парсинга. Получилось очень быстро транслировать официальную грамматику css 2.1. Сейчас работаю над маппингом css на dom. Делаю это через реверсное дерево. Результатами пока доволен (не выкладывал еще на гит, т.к. маппинг еще даже на 50% не доделан). По поводу CsQuery и вообще XPath — это крайне неэффективный вариант. В случае использования XPath придется проходить по всем css селекторам по всему dom. Это очень накладно по ресурсам. Гораздо проще иметь подготовленную CSS таблицу и для каэждого элемента DOM искать нужные правила в ней. Дерево в этом плане лучший помощник.
Я упомянул CsQuery в том плане, что связанные с CSS фичи в ней можно было бы развить, соответственно, нужно выяснить, каких фич автору не хватает. Если я надумаю реализовывать маппинг, то изобретать ничего не буду, снова портирую код Firefox. Но я не уверен, что это вообще кому-нибудь надо. Браузер на C#, вроде, никто не пишет. :) Вы сами как используете? И не понял — библиотека есть на гитхабе или нет? Ссылка?

Получилось очень быстро транслировать официальную грамматику css 2.1.

Только 2.1? Не старовато ли?

Для CSS 2.1, вроде, вообще практическая готовая грамматика в стандарте есть, если память не изменяет. Только она обработку ошибок не включает. Собственно, ExCSS из-за этого проблемы имеет: грамматика есть, а обработка ошибок — пиши пропало. В диком окружающем мире с CSS-хаками и с дикой скоростью развивающимся языком без правильной обработки ошибок никак.
Вы сами как используете?

Хочу сделать рендеринг страниц на python. Многие сайты делают скриншоты url'ов. Используют для этого либо сторонние сервисы, либо браузеры через какие-то хаки. Вот хочу сделать собственный рендер. Но это так, мечтаю пока. На самом деле применений этому куча. При корректном маппинге и работающей box-модели можно без проблем получать основной текст страницы игнорируя сайдбары и рекламу, ну или делать минификацию css например.. так вот.

Только 2.1? Не старовато ли?

А спецификация css3 официально не готова еще. Последняя официальная стабильная версия css — это 2.1

Для CSS 2.1, вроде, вообще практическая готовая грамматика в стандарте есть

Есть, но допиливать все равно надо. Плюс построение модели по токенам в любом случае ручками.

Только она обработку ошибок не включает

В самой грамматике есть варианты ошибочных токенов: badstring, badcomment, baduri. При правильном использовании этих токентов можно нормально жить и с ошибками в css. Я с этим не заморачивался и просто пропускаю ошибочные с точки зрения грамматики токены. Парсер не валится. Проверял на реальных css от google и stackoverflow. У них куча всяких css3 вставок и хаков для IE, но парсер их просто пропускает если не может распознать.

ExCSS

Не трогал её, но если она постороена строго по грамматике, то не должна валиться. По спецификации неправильные правила, селекторы и значения просто пропускаются.

библиотека есть на гитхабе или нет

PyFox. Там лежит только парсер. На ноуте лежит недоделанный маппинг и всякие css3 улучшения. Может через неделю-две обновлю репу.
Вот хочу сделать собственный рендер.

По-моему, это безумная затея. :) Это же совершенно невменяемое количество кода. Написания движка браузера с нуля, разве что без динамики. Ну, может, CSS 2.1 с грехом напополам как-то отрендерить и получится (с грехом напополам — потому что есть множество неприятных крайних случаев: ошибки округления, quirks и т.п.), но практическая ценность тогда под вопросом, потому что CSS 3 используется повсеместно.

А спецификация css3 официально не готова еще. Последняя официальная стабильная версия css — это 2.1

Спецификация CSS 3 никогда не будет готова, потому что не существует. :) Её разбили на отдельные модули, и они теперь живут и развиваются сами по себе. Те же селекторы и медиа-запросы — уже рекомендация (то есть стандарт).

На ноуте лежит недоделанный маппинг и всякие css3 улучшения. Может через неделю-две обновлю репу.

Почему не заливать в реальном времени? Я сам без синхронизации через гитхаб не могу, так как работаю на нескольких компьютерах, да и спокойнее как-то, когда код надёжно сохранён на гитхабе (веры винтам нет, дохнут как собаки).
По-моему, это безумная затея

Ну по времени реализации этой затеи я не ограничен :) Веб — это моя работа. Мне интересно это писать прежде всего для себя, чтобы лучше понимать как работают браузеры и с какими проблемами они сталкиваются.
Например, теперь я знаю, что чем проще селектор, тем проще браузеру его обработать. Капитан очевидность? Ну вот раньше я думал что чем больше мы сужаем область селектора, тем проще браузеру его выцепить: div.someclass — сузил область и вроде бы теперь-то браузер должен быстрее нужные правила цеплять. А в реальности получается что браузер при маппинге должен проме поиска селектора еще и сравнивать теги. По этой же причине не стоит писать p#identifier или span.class1.class2. Псевдо-классы :nth-child :last :first и т.д. тоже существенно замедляют наложение.
В общем это может быть и не практичная идея, но очень интересное занятие, поднимающее уровень знаний.

CSS 3 используется повсеместно

Ну так я не говорю что ограничиваюсь css2.1, просто на базе грамматики css2.1 постепенно внедряю css3. Ну и большинство сайтов имеет fallback для браузеров не поддерживающих css3 (IE6,7,8?). Мало кто разрешает верстальщикам резать сайты под самые последние браузеры без оглядки назад. Ну и кстати реального использования CSS3 селекторов в вебе не так много, разве что часто используют '+'. По большей части css3 пытаются упихнуть в свойства, а парсеру на это наплевать. Так что проблема парсинга css3 — в основном это проблема парсинга селекторов.

Почему не заливать в реальном времени

По работе привык в remote класть только логически завершенные части.
В общем это может быть и не практичная идея

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

Ну и большинство сайтов имеет fallback для браузеров не поддерживающих css3 (IE6,7,8?).

IE6 и IE7, в общем-то, мертвы, под них практически никто не верстает. IE8 отмирает. Гугл в популярных проектах забивает на IE8, банальный jQuery 2 не поддерживает IE8. Часто вижу фиксы на JS вместо CSS. В общем, я бы не рассчитывал на то, что поддержка IE8 просуществует существенное время.

Так что проблема парсинга css3 — в основном это проблема парсинга селекторов.

Ещё медиа-запросы, по-моему, довольно популярны.
медиа-запросы можно игнорировать в зависимости от задачи. Но опять же. Никакой проблемы парсить их нету. То, что firefox и chrome обладают космическими скоростями рендеринга и за пазухой у них сотни мегабайт исходников еще не значит что это нельзя написать проще, пусть и работать все будет несколько медленнее. Зато работать будет на любой кофеварке, для которой существует интерпретатор python.
Для тех же популярных библиотек генераторов PDF из HTML до сих пор нету вменяемых рендеров…
UFO just landed and posted this here
Ну это наверное как спросить в начале 2000х зачем ты делаешь свой веб-сервер, ведь есть apache с кучей модулей и обширной функциональностью.
PhantomJS — все же обрезанный вебкит браузер. Все тот же код с теми же ошибками. Ничего против этого не имею, но хочу сделать свое, на чистом питоне, в виде отдельных библиотек отвечающих каждая за свой кусок функционала. Не претендую на замену или какое-то реальное использование, просто пишу для себя. Может потом эти наработки еще найдут применение где-то.
Это другой подход к написанию, с другими алгоритмами и немножко другими целями.
UFO just landed and posted this here
Стоп-стоп-стоп.
Я ни на кого бочку не качу и на создание альтернативного браузера не претендую :)
Мои запросы намного скромнее. Я хочу всего лишь иметь нормальный маппинг свойств на элементы и уметь строить страницу на этой основе.
Вы сейчас разговариваете со мной с позиции клиента, которому я якобы пытаюсь впихнуть свою поделку а вы защищаетесь существующими решениями.
Но я ведь никому ничего не продаю :) Я всего лишь сказал что я тоже сделал свой парсер, и имею кое-какие планы, исключительно ради исследовательских целей. Все. Не надо критиковать мои мечты :)
Я еще толком кроме парсера и полу-маппинга ничего не сделал.
Говоря про «тот же код» я имел ввиду что этот тот же вебкит, только вид сбоку. Не хотел обидеть никого.
UFO just landed and posted this here
Спасибо :) Готовые решения не интересуют потому что такой проблемы нету. Этот проект что-то типа очередного калькулятора, только в других масштабах.
Мне год назад понадобилось из CSS сделать SCSS, в котором уже все правила будут как надо вложены и удалены, если были лишними. Написал простейший парсер Text -> AST парсер на Немерле PEG. Если интересно, то можете посмотреть, как коротко можно записать весь парсер: bitbucket.org/ionoy/sassoptimize/src/5965ddb5fcbea9692fae3b4a393117651654ff37/Parser.n
Это ни в коем случае не конкурент вашему проекту, там кроме преобразования текста в АСТ ничего нету, но может быть будет любопытно посмотреть.
Вещь хорошая, но довольно специфичная. Вряд ли кому-то нужно прямо сейчас. Но если запилить анонс на codeproject.com, то шансы на активное использование со временем существенно вырастут.
Да, были мысли на CodeProject написать. Он всё-таки в гугле по запросу «c# css parser» идёт сразу после StackOverflow с его мегапопулярными, но (нецензурная брань) заблокированными вопросами. ExCSS тоже изначально родом с CodeProject.

Но есть нюанс: как так написать, чтобы английский был похож на английский? Или текст как у меня ReadMe прокатит? Не хотелось бы получать нелестные отзывы только из-за кривого языка (или на CP к этому терпимо относятся?).

Ещё надо будет на NuGet обязательно выложить, чтобы заметили. С YaLinqo (LINQ to Objects на PHP) вышло — после выкладывания на Packagist его начали замечать. :)
Главное, чтобы было понятно (что не понятно — спросят). На англоязычных ресурсах в общем-то привыкли к тому, что туда пишут иностранцы, для которых английский не является родным. Значение имеет качество кода и полезность библиотеки.

NuGet — да, отличная идея.
Извините за офтоп, но чем вы делали картинку из начала поста (ну кусок кода из readme под наклоном), есть какой то сервис для этого? Хотелось бы сделать нечто подобное для пары своих проектов.
Only those users with full accounts are able to leave comments. Log in, please.