-
Notifications
You must be signed in to change notification settings - Fork 2
Play with explicit AST #20
Conversation
I quite like having an AST, but since this AST represents a strict superset of valid selectors, it adds a bit of complexity as I worry about whether an AST could be produced which doesn't corresponding to a valid selector. I guess that issue is implicit in the current implementation, but at least it doesn't stand out so much. |
ideally a good AST should make invalid selectors unrepresentable; just to be clear, the case I can see is a "rootless" selector. |
222cc12
to
1fbd1e0
Compare
hmm, no actually the Root path enum variant must be present otherwise the type recursion doesn't terminate; |
is it because the this AST allows: |
Yes, precisely. |
df1f6c6
to
1641fd5
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good. Just a couple of nits on the tree diagrams.
ok, so now I fixed the AST data model so that I'd like to see how hard it would be to also make |
That selector is valid and should be representable. Try the following tests:
|
src/ast.rs
Outdated
/// ^ \ | ||
/// / \ [Number(1), Number(2)] | ||
/// / \ | ||
/// Root ___/ \___ DotName("foo") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The two diagrams still seem inconsistent. I'd expect the part of the tree nearest the root to be identical in both cases since $.foo
is a common prefix of both selectors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's because the expressions have right to left precedence
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still don't get it. $.foo.bar
produces the AST:
Sel(Sel(Root, DotName("foo")), DotName("bar"))
and $.foo[1,2]["bar"]
produces:
Sel(Sel(Sel(Root, DotName("foo")), Union([Number(1), Number(2)])), Union([Field("bar")]))
Root
appears inside Sel(Root, DotName("foo"))
in both cases. Shouldn't this subtree look the same in both diagrams?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Uh :brainfart:; fixed
Value::Object(m) => Box::new(m.values()), | ||
Value::Array(a) => Box::new(a.iter()), | ||
_ => Box::new(std::iter::empty()), | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really like the readability of this approach. (It's a pity Box::new
can't be factored out of the outer match, but that's rust for you.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hopefully soon rust will have the box
keyword which at least removes the need for extra parentheses
Ah yes, you're right |
1031ec9
to
d35dad7
Compare
/// ``` | ||
/// | ||
/// Selectors are left associative, thus `$.foo[1,2]["bar"]` behaves | ||
/// like (pseudocode) `(($.foo)[1,2])["bar"]`; thus the root of the resulting |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it worth pointing out that the Root
selector ($
) is not related to the root of the AST? Might confuse people otherwise.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few naming issues. What else do you have in mind for this PR before it is ready for merging?
nothing that can't be added in smaller subsequent PRs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great. Thanks!
This is just a draft to see whether walking the pest parse tree becomes easier to reason about if we implement the interpreter around an abstract syntax tree instead of using a chain of selectors.
Probably it could become even simpler if I tweaked the grammar a bit, but I resisted doing that in the first pass.
One of the most interesting aspects of this approach is that the pest parse tree could be, in principle, mechanically mapped on on an abstract tree, using tools such as pest_ast+pest_derive