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

Change Edge::label from optional to required #1205

Merged
merged 28 commits into from
Feb 4, 2025
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
b018180
Make `Edge::label` required instead of optional.
mjoerussell Dec 30, 2024
b12b4c1
Update generated files
mjoerussell Dec 30, 2024
bba6f4a
Remove unused import in cst_output/renderer
mjoerussell Dec 30, 2024
da6265a
Update crates/codegen/runtime/cargo/wasm/src/runtime/interface/genera…
mjoerussell Jan 2, 2025
35bd99c
Update crates/codegen/runtime/cargo/crate/src/runtime/cst/edge_label.…
mjoerussell Jan 2, 2025
ecb20e3
Update crates/codegen/runtime/cargo/wasm/src/runtime/interface/genera…
mjoerussell Jan 2, 2025
5ef9fd4
Clean up usage of IntoFFI::_into_ffi()
mjoerussell Jan 2, 2025
049dd40
Return `Option<Edge>` from `Helper::current()` instead of `Option<(Ed…
mjoerussell Jan 2, 2025
8d1e175
Don't skip root nodes in `Helper::current()`
mjoerussell Jan 2, 2025
26729fa
* Change `Parent::Open` to `Parent::Connected` and `Parent::Closed` t…
mjoerussell Jan 3, 2025
790f5d5
Rename `Edge::anonymous()` to `Edge::root()`
mjoerussell Jan 3, 2025
4b5c352
Print all edge labels in snapshot tests
mjoerussell Jan 3, 2025
819da29
Add an `Unrecognized` label for `Unrecognized` nodes
mjoerussell Jan 3, 2025
bb853b4
Merge branch 'main' into feature/required-label
mjoerussell Jan 3, 2025
ea69bba
Update doc comments for edge label wit definitions.
mjoerussell Jan 8, 2025
19166e1
Merge branch 'main' into feature/required-label
mjoerussell Jan 10, 2025
756deb9
Add changeset
mjoerussell Jan 13, 2025
0eca315
Add `PredefinedLabel::Missing` to represent nodes that could not be r…
mjoerussell Jan 14, 2025
8515650
Merge branch 'main' into feature/required-label
mjoerussell Jan 14, 2025
2a23b0e
* Add some utility functions to `Cursor` to help users determine the …
mjoerussell Jan 17, 2025
eac3e13
When failing a cst_output test, print the failed tree to stderr so th…
mjoerussell Jan 21, 2025
337fbfa
Fix incorrect labels on partially-parsed separators.
mjoerussell Jan 21, 2025
3f28258
When recovering from errors when parsing Pratt expressions, give the …
mjoerussell Jan 22, 2025
68614b2
Merge branch 'main' into feature/required-label
mjoerussell Jan 23, 2025
18157e3
Bump change type from 'patch' to 'minor'
mjoerussell Jan 23, 2025
6eec07b
Merge branch 'main' into feature/required-label
mjoerussell Feb 3, 2025
2c6e5f5
* Clean up checks for root labels in descendant nodes using new APIs
mjoerussell Feb 4, 2025
07368d2
Merge branch 'main' into feature/required-label
mjoerussell Feb 4, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
5 changes: 5 additions & 0 deletions .changeset/metal-penguins-flow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@nomicfoundation/slang": patch
OmarTawfik marked this conversation as resolved.
Show resolved Hide resolved
---

Make `Edge::label` a required field instead of being optional.
12 changes: 6 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions crates/codegen/language/definition/src/model/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,9 @@ pub struct Topic {
)]
#[strum(serialize_all = "snake_case")]
pub enum PredefinedLabel {
Root,
Unrecognized,
Missing,
Item,
Variant,
Separator,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,9 @@ pub enum EdgeLabel {
}

impl crate::cst::EdgeLabelExtensions for EdgeLabel {}

impl Default for EdgeLabel {
fn default() -> Self {
Self::Root
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,7 @@ pub(crate) trait Lexer {
let end = input.position();

ParserResult::r#match(
vec![Edge::anonymous(Node::terminal(
kind,
input.content(start..end),
))],
vec![Edge::root(Node::terminal(kind, input.content(start..end)))],
vec![],
)
}
Expand Down Expand Up @@ -132,10 +129,7 @@ pub(crate) trait Lexer {
return ParserResult::no_match(vec![kind]);
}
let end = input.position();
children.push(Edge::anonymous(Node::terminal(
kind,
input.content(start..end),
)));
children.push(Edge::root(Node::terminal(kind, input.content(start..end))));

let restore = input.position();
if let ParserResult::Match(r#match) = self.trailing_trivia(input) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use std::rc::Rc;

use crate::cst::{
Edge, Node, NonterminalKind, NonterminalNode, TerminalKind, TerminalKindExtensions, TextIndex,
Edge, EdgeLabel, Node, NonterminalKind, NonterminalNode, TerminalKind, TerminalKindExtensions,
TextIndex,
};
use crate::parser::lexer::Lexer;
use crate::parser::parser_support::context::ParserContext;
Expand Down Expand Up @@ -81,13 +82,16 @@ where
}
}
let input = &input[start.utf8..];
let kind = if input.is_empty() {
TerminalKind::MISSING
let (kind, label) = if input.is_empty() {
(TerminalKind::MISSING, EdgeLabel::Missing)
} else {
TerminalKind::UNRECOGNIZED
(TerminalKind::UNRECOGNIZED, EdgeLabel::Unrecognized)
};

let node = Node::terminal(kind, input.to_string());
children.push(Edge::anonymous(node));

children.push(Edge { label, node });

ParseOutput {
tree: Rc::new(NonterminalNode::new(topmost_kind, children)),
errors: vec![ParseError::new(
Expand Down Expand Up @@ -136,14 +140,18 @@ where
} else {
start
};
let kind = if input[start..].is_empty() {
TerminalKind::MISSING
let (kind, label) = if input[start..].is_empty() {
(TerminalKind::MISSING, EdgeLabel::Missing)
} else {
TerminalKind::UNRECOGNIZED
(TerminalKind::UNRECOGNIZED, EdgeLabel::Unrecognized)
};

let skipped_node = Node::terminal(kind, input[start..].to_string());
let mut new_children = topmost_node.children.clone();
new_children.push(Edge::anonymous(skipped_node));
new_children.push(Edge {
label,
node: skipped_node,
});

let start_index = stream.text_index_at(start);
let mut errors = stream.into_errors();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,18 +47,18 @@ impl ParserResult {
pub fn with_kind(self, new_kind: NonterminalKind) -> ParserResult {
match self {
ParserResult::Match(r#match) => ParserResult::r#match(
vec![Edge::anonymous(Node::nonterminal(new_kind, r#match.nodes))],
vec![Edge::root(Node::nonterminal(new_kind, r#match.nodes))],
r#match.expected_terminals,
),
ParserResult::IncompleteMatch(incomplete_match) => ParserResult::incomplete_match(
vec![Edge::anonymous(Node::nonterminal(
vec![Edge::root(Node::nonterminal(
new_kind,
incomplete_match.nodes,
))],
incomplete_match.expected_terminals,
),
ParserResult::SkippedUntil(skipped) => ParserResult::SkippedUntil(SkippedUntil {
nodes: vec![Edge::anonymous(Node::nonterminal(new_kind, skipped.nodes))],
nodes: vec![Edge::root(Node::nonterminal(new_kind, skipped.nodes))],
..skipped
}),
ParserResult::NoMatch(no_match) => ParserResult::no_match(no_match.expected_terminals),
Expand All @@ -74,13 +74,13 @@ impl ParserResult {
label: prev_label, ..
}) = self.significant_node_mut()
{
*prev_label = Some(label);
*prev_label = label;
}
// Also allow to name a single trivia terminal node
else if let ParserResult::Match(Match { nodes, .. }) = &mut self {
if let [node] = nodes.as_mut_slice() {
if node.as_terminal().is_some_and(|tok| tok.kind.is_trivia()) {
node.label = Some(label);
node.label = label;
}
}
}
Expand Down Expand Up @@ -173,7 +173,7 @@ impl PrattElement {
Self::Binary { kind, nodes, .. }
| Self::Prefix { kind, nodes, .. }
| Self::Postfix { kind, nodes, .. } => {
vec![Edge::anonymous(Node::nonterminal(kind, nodes))]
vec![Edge::root(Node::nonterminal(kind, nodes))]
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ impl PrecedenceHelper {
let left_nodes = match left {
Some(Expression { nodes }) => {
vec![Edge {
label: Some(left_label),
label: left_label,
node: Node::nonterminal(child_kind, nodes),
}]
}
Expand All @@ -185,7 +185,7 @@ impl PrecedenceHelper {
let right_nodes = match right {
Some(Expression { nodes }) => {
vec![Edge {
label: Some(right_label),
label: right_label,
node: Node::nonterminal(child_kind, nodes),
}]
}
Expand All @@ -197,7 +197,7 @@ impl PrecedenceHelper {

Expression {
nodes: vec![Edge {
label: Some(EdgeLabel::Variant),
label: EdgeLabel::Variant,
node: Node::nonterminal(kind, children),
}],
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,16 @@ impl SeparatedHelper {
match skip_until_with_nested_delims::<_, LexCtx>(input, lexer, separator) {
// A separator was found, so we can recover the incomplete match
Some((found, skipped_range)) if found == separator => {
let kind = if skipped_range.is_empty() {
TerminalKind::MISSING
let (kind, label) = if skipped_range.is_empty() {
(TerminalKind::MISSING, EdgeLabel::Missing)
} else {
TerminalKind::UNRECOGNIZED
(TerminalKind::UNRECOGNIZED, EdgeLabel::Unrecognized)
};
accum.push(Edge::anonymous(Node::terminal(
kind,
input.content(skipped_range.utf8()),
)));

accum.push(Edge {
label,
node: Node::terminal(kind, input.content(skipped_range.utf8())),
});
input.emit(ParseError::new(
skipped_range,
incomplete.expected_terminals,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,15 +155,16 @@ impl SequenceHelper {
});
debug_assert_eq!(next_terminal, Ok(Some(running.found)));

let kind = if running.skipped.is_empty() {
TerminalKind::MISSING
let (kind, label) = if running.skipped.is_empty() {
(TerminalKind::MISSING, EdgeLabel::Missing)
} else {
TerminalKind::UNRECOGNIZED
(TerminalKind::UNRECOGNIZED, EdgeLabel::Unrecognized)
};
running.nodes.push(Edge::anonymous(Node::terminal(

running.nodes.push(Edge{label, node: Node::terminal(
kind,
std::mem::take(&mut running.skipped),
)));
)});
running.nodes.extend(next.nodes);

self.result = State::Running(ParserResult::Match(Match {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,8 @@ interface cst {

/// Represents a connection between nodes in the syntax tree.
record edge {
/// Optional label describing the relationship between nodes.
label: option<edge-label>,
/// Describes the relationship between this node and its parent.
label: edge-label,
/// The target node of this edge.
node: node,
}
Expand All @@ -168,8 +168,8 @@ interface cst {

/// Returns the current node under the cursor.
node: func() -> node;
/// Returns the label of the edge from the parent to the current node, if any.
label: func() -> option<edge-label>;
/// Returns a label that describes the relationship between the current node and its parent.
label: func() -> edge-label;

/// Returns the current text offset of the cursor.
text-offset: func() -> text-index;
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading