Skip to content

Merge new CSS parser

Benjamin Otte requested to merge wip/otte/css into master

I have no idea who wants to review this, but the branch got a bit large, so I wanted to write down in a high level what I've been up to here so people can follow along.

This branch merges parts of a rework of the CSS parsing infrastructure that I did in early 2016 but never landed because it was deemed to unwieldy and also, we got into the 3.90 discussion.
I've recently found it again when I wanted to use CSS-like syntax in various places of the code, such as:

  • gsk_transform_parse()
  • moving the node serialization to a text-based format

This branch achieves the following 3 goals:

  1. It makes CSS parsing compliant with the CSS syntax spec.
    It's no longer a hastily thrown together manual parser using mostly strpbrk(). This avoids weird bugs that we had where we didn't properly parse some complex CSS values in corner cases (my favorite one is font: 100px Sans not working - you have to use 99 or 101).

  2. It has way better error locations in error reporting.
    While the old parser usually got the line numbers right so it was good enough to find the location one was looking for, it showed rather erratic behavior when underlining things in the inspector. The new parser allows tracking exact locations so it does give out byte-perfect error messages.

  3. The GtkCssParser object has a usable API.
    Because I want to use CSS parsing in various places in GTK, it helps if there is a parser that can easily be used. The old API again was cobbled together to be good enough, but missed various features that would have made it easy to reuse.

And finally, here's a high-level overview on how I did all of this:

  1. Introduce a static libgtkcss in the new gtk/css/ subdirectory and add the tokenizer from the old branch to it. This library can now be linked into GDK and GSK for parsing CSS.

  2. Introduce the new parser's APIs (remember: that parser already exists in a different branch) on top of the old parser and port existing code - usually that involves making use of CSS tokens, so that calls like _gtk_css_parser_begins_with(parser, ',') are replaced with gtk_css_parser_has_token(parser, GTK_CSS_TOKEN_COMMA).

  3. Once, as much as possible has been converted, swap the old parser with the new parser and fix the remaining APIs. This is a rather large commit, because the new parser tracks blocks (a block is anything between round/curly/square brackets) and makes sure open blocks are properly closed.

  4. Fix some of the most egregious cases of parser abuse by redoing it from scratch using the new parser APIs.

  5. Now that the new parser does proper error reporting, it is no longer necessary to do it inside GtkCssSection. Remove the code that did it and use GtkCssSection as the object to refer to areas in a CSS file in error messages: It now just contains the GFile and the start and end location of the error or warning.

  6. Clean up error handling to use the new parser's capabilities and report errors properly.

  7. Make the testsuite expose the new accurate error locations and update the reference output for it.

  8. Add gsk_transform_parse() and use it in GtkBuilder.

  9. Start fixing reftests now that GtkFixed can be used inside reftests.

The whole branch is done btw and can be merged. I just want to give people time to have a look and not just merge it immediately. The reason I'm still pushing here is because that's a batch of work I want to do that depends on this branch (like the reftests fixage), and I can't push that to master.

Edited by Benjamin Otte

Merge request reports