Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Include an explicit Combinator in the AST for implicit descendant #61

Conversation

flavorjones
Copy link
Collaborator

@flavorjones flavorjones commented Jun 4, 2024

Making the descendant combinator explicit (where previously it was implicit by having two CompoundSelectors next to each other in a ComplexSelector) makes consuming the AST easier for visitors, and simplifies the selectors parser and its handling of whitespace.

This is an alternative to #60.

Making the descendant combinator explicit (where previously it was
implicit by having two CompoundSelectors next to each other in a
ComplexSelector) makes consuming the AST easier for visitors, and
simplifies the parser.
@flavorjones flavorjones force-pushed the flavorjones-complex-selector-whitespace2 branch from 76dd561 to 278edb5 Compare June 5, 2024 17:23
@flavorjones
Copy link
Collaborator Author

I also think this is preferable to #60 because it allows us to make this additional change:

diff --git a/lib/syntax_tree/css/selectors.rb b/lib/syntax_tree/css/selectors.rb
index f8dbe6c5..fbae220b 100644
--- a/lib/syntax_tree/css/selectors.rb
+++ b/lib/syntax_tree/css/selectors.rb
@@ -295,7 +295,11 @@ def initialize(tokens)
       end

       def parse
-        selector_list
+        selector_list.tap do
+          unless EOFToken === tokens.peek
+            raise ParseError.new "Unexpected token: #{tokens.peek.value.inspect}"
+          end
+        end
       end

and then a malformed selector like div::first-line.xl will result in an exception like:

SyntaxTree::CSS::Selectors::ParseError: Unexpected token: "."

The code on the branch in #60 will happily parse this as two compound selectors, [div::first-line, .xl], which is incorrect behavior IMHO.

@kddnewton
Copy link
Member

So I think this is illustrating an issue with the design of ComplexSelector. Previously it was a left, a combinator, and a right. Now it's a flat list. This puts it on the consumer to understand what is implied by the flat list.

Thinking about html > body > main div I think I would prefer that to look like:

(complex-selector
  (complex-selector
    (complex-selector
      (type-selector (wqname (ident-token "html")))
      (combinator (delim-token ">"))
      (type-selector (wqname (ident-token "body")))
    )
    (combinator (delim-token ">"))
    (type-selector (wqname (ident-token "main")))
  )
  (combinator (whitespace-token " "))
  (type-selector (wqname (ident-token "div")))
)

This makes the hierarchy clear, and has the benefit of not requiring any parsing from the consumer. What do you think?

@flavorjones
Copy link
Collaborator Author

I think I would prefer that to look like ...

You said the opposite in #58 (comment) ! 😆

If you prefer the original way, I'm happy to roll that up into this PR, give me a little bit.

@kddnewton
Copy link
Member

Shit, I totally did. Damnit. Sorry!

The other thing we could do which might make this nicer is we could define types for each combinator instead of having it all be the same thing.

So, DirectDescendentSelector and DescendentSelector and SiblingSelector and so on. That might be a better experience.

@flavorjones
Copy link
Collaborator Author

define types for each combinator

Yup, I will be sending a PR to do that, but I wanted to sort out this PR first ...

I do slightly prefer the flat list (with proper Combinator types) because there's no operator precedence to worry about that would require proper binary operators.

Do you want me to add a commit introducing Combinator types?

@kddnewton
Copy link
Member

Ahh of course, that was what you were saying earlier. Sorry I must be slow today I'm finally catching up.

Yeah, let's look at what combinator types would look like. At the moment I'm mostly reacting to having to look at "WhitespaceToken" to understand how to handle it, which is making it feel bad.

@flavorjones
Copy link
Collaborator Author

@kddnewton OK, pushed a commit introducing the subclasses. LMK if you want a different approach (there are obviously alternatives to using constants the way I did)

Where the AST was previously

```
Selectors::ComplexSelector[
  child_nodes: [
    Selectors::TypeSelector[value: { name: { value: "section" } }],
    Selectors::Combinator[value: { value: ">" }],
    Selectors::TypeSelector[value: { name: { value: "table" } }]
  ]
]
```

it's now

```
Selectors::ComplexSelector[
  child_nodes: [
    Selectors::TypeSelector[value: { name: { value: "a" } }],
    Selectors::DescendantCombinator,
    Selectors::TypeSelector[value: { name: { value: "b" } }],
    Selectors::ChildCombinator,
    Selectors::TypeSelector[value: { name: { value: "c" } }],
    Selectors::NextSiblingCombinator,
    Selectors::TypeSelector[value: { name: { value: "d" } }],
    Selectors::SubsequentSiblingCombinator,
    Selectors::TypeSelector[value: { name: { value: "e" } }],
    Selectors::ColumnSiblingCombinator,
    Selectors::TypeSelector[value: { name: { value: "f" } }],
  ]
]
```
@flavorjones
Copy link
Collaborator Author

I'm noticing now that all the combinator classes are dispatched with visit_combinator, LMK if you think it makes more sense to split it up into multiple methods.

Copy link
Member

@kddnewton kddnewton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah this looks good. I think I'm going to change the PP_NAME to be a method call, but other than that I think this is good.

@kddnewton kddnewton merged commit f9f7b3e into ruby-syntax-tree:main Jun 28, 2024
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants