✨ feat(selector): add recursive descent selector (..)#1234
Conversation
Add a new `..` recursive selector that matches and returns all descendant nodes of a markdown element. Rename `TokenKind::RangeOp` to `TokenKind::DoubleDot` to clarify its dual role as both the range operator and the recursive selector token. Refactor `eval_selector` to return `RuntimeValue` directly instead of `bool`.
There was a problem hiding this comment.
Pull request overview
Adds a .. recursive descent selector to return all descendant Markdown nodes and updates the language pipeline to treat selectors as value-producing expressions rather than boolean predicates.
Changes:
- Introduces
Selector::Recursive(..) and parses it through lexer/CST/AST. - Renames
TokenKind::RangeOptoTokenKind::DoubleDotand wires it through parsers. - Refactors
eval_selectorto returnRuntimeValue, adding recursive traversal evaluation.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| crates/mq-markdown/src/node.rs | Adds a children() accessor used to traverse descendants for ... |
| crates/mq-lang/src/selector.rs | Adds the Recursive selector and display/parse tests. |
| crates/mq-lang/src/lexer/token.rs | Renames token kind for .. to DoubleDot. |
| crates/mq-lang/src/lexer.rs | Emits TokenKind::DoubleDot for ... |
| crates/mq-lang/src/eval/builtin.rs | Changes selector evaluation to return RuntimeValue; implements recursive descent. |
| crates/mq-lang/src/eval.rs | Adapts evaluator to new selector return type. |
| crates/mq-lang/src/cst/parser.rs | Updates CST parsing to accept DoubleDot where RangeOp was used. |
| crates/mq-lang/src/ast/parser.rs | Updates AST parsing/precedence and introduces .. as a selector expression. |
CodSpeed Performance ReportMerging this PR will not alter performanceComparing Summary
|
Co-authored-by: Copilot <[email protected]>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
crates/mq-lang/src/cst/parser.rs:1
- The
DoubleDotselector branch returnsnodewithout attachingchildren(and likely without recording the selector token in the CST), unlike theTokenKind::Selector(_)branch. This can lead to an incomplete CST node for... Align theDoubleDothandling with the selector path by populating the CST children/token consistently.
use std::{collections::BTreeSet, fmt::Display, iter::Peekable};
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.
Comments suppressed due to low confidence (1)
crates/mq-lang/src/cst/parser.rs:1
TokenKind::DoubleDotreturnsnodewithout showing how it gets converted into aSelector::RecursiveCST node (unlike the AST parser which explicitly mapsDoubleDot→Selector::Recursive). This risks producing an incorrect/empty selector node in the CST. Suggest explicitly setting the selector kind forDoubleDothere (or updateSelector::try_from(&Token)/ token-to-selector conversion to supportTokenKind::DoubleDotdirectly, and then reuse the same path as other selectors).
use std::{collections::BTreeSet, fmt::Display, iter::Peekable};
| pub fn eval_selector(node: &mq_markdown::Node, selector: &Selector) -> RuntimeValue { | ||
| let is_match = match selector { |
There was a problem hiding this comment.
eval_selector now constructs RuntimeValue::Markdown(node.clone(), None) on match, which can drop existing per-value metadata carried in the second field of RuntimeValue::Markdown (previously preserved by returning runtime_value.clone() in eval_selector_expr). Consider either (a) keeping eval_selector as a predicate and letting the caller return the original RuntimeValue, or (b) changing eval_selector to accept the full &RuntimeValue (or metadata) so it can preserve the original (node, meta) for non-recursive selectors.
Add a new
..recursive selector that matches and returns all descendant nodes of a markdown element. RenameTokenKind::RangeOptoTokenKind::DoubleDotto clarify its dual role as both the range operator and the recursive selector token. Refactoreval_selectorto returnRuntimeValuedirectly instead ofbool.