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

Open
wants to merge 19 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
19 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
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
  •  
  •  
  •  
2 changes: 2 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,8 @@ pub struct Topic {
)]
#[strum(serialize_all = "snake_case")]
pub enum PredefinedLabel {
Root,
Unrecognized,
Item,
Variant,
Separator,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,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(None, 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,6 +1,6 @@
use std::rc::Rc;

use crate::cst::{Edge, Node, TerminalKind, TerminalKindExtensions, TextIndex};
use crate::cst::{Edge, EdgeLabel, Node, TerminalKind, TerminalKindExtensions, TextIndex};
use crate::parser::lexer::Lexer;
use crate::parser::parser_support::context::ParserContext;
use crate::parser::parser_support::parser_result::{
Expand Down Expand Up @@ -84,11 +84,18 @@ where
} else {
TerminalKind::UNRECOGNIZED
};

let label = if kind == TerminalKind::UNRECOGNIZED {
EdgeLabel::Unrecognized
} else {
EdgeLabel::default()
};

let node = Node::terminal(kind, input.to_string());
let tree = if no_match.kind.is_none() || start.utf8 == 0 {
node
} else {
trivia_nodes.push(Edge::anonymous(node));
trivia_nodes.push(Edge { label, node });
Node::nonterminal(no_match.kind.unwrap(), trivia_nodes)
};
ParseOutput {
Expand Down Expand Up @@ -144,9 +151,19 @@ where
} else {
TerminalKind::UNRECOGNIZED
};

let label = if kind == TerminalKind::UNRECOGNIZED {
EdgeLabel::Unrecognized
} else {
EdgeLabel::default()
};

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 @@ -48,18 +48,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) => {
Expand All @@ -77,13 +77,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 @@ -176,7 +176,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 @@ -56,10 +56,17 @@ impl SeparatedHelper {
} else {
TerminalKind::UNRECOGNIZED
};
accum.push(Edge::anonymous(Node::terminal(
kind,
input.content(skipped_range.utf8()),
)));

let label = if kind == TerminalKind::UNRECOGNIZED {
EdgeLabel::Unrecognized
} else {
EdgeLabel::default()
};

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 @@ -160,10 +160,17 @@ impl SequenceHelper {
} else {
TerminalKind::UNRECOGNIZED
};
running.nodes.push(Edge::anonymous(Node::terminal(

let label = if kind == TerminalKind::UNRECOGNIZED {
EdgeLabel::Unrecognized
} else {
EdgeLabel::default()
};

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 @@ -142,7 +142,7 @@ interface cst {
/// Represents a connection between nodes in the syntax tree.
record edge {
/// Optional label describing the relationship between nodes.
label: option<edge-label>,
label: edge-label,
/// The target node of this edge.
node: node,
}
Expand All @@ -167,7 +167,7 @@ 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>;
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.

Original file line number Diff line number Diff line change
Expand Up @@ -147,40 +147,38 @@ impl Helper {
}

fn try_select(&mut self, target_label: EdgeLabel) -> Option<Node> {
let (label, node) = self.current()?;
let edge = self.current()?;

if label == target_label {
if edge.label == target_label {
self.index += 1;
Some(node.clone())
Some(edge.node)
} else {
None
}
}

fn current(&mut self) -> Option<(EdgeLabel, Node)> {
fn current(&mut self) -> Option<Edge> {
loop {
let Edge { label, node } = self.node.children.get(self.index)?;
let edge = self.node.children.get(self.index)?;

match label {
// Skip unlabeled nodes:
| None
match edge.label {
// Skip trivia:
| Some(EdgeLabel::LeadingTrivia | EdgeLabel::TrailingTrivia) => {
| EdgeLabel::LeadingTrivia | EdgeLabel::TrailingTrivia => {
self.index += 1;
continue;
}
// Otherwise, return the edge:
Some(other_label) => {
return Some((*other_label, node.clone()));
_ => {
return Some(edge.clone());
}
}
}
}

fn finalize(mut self) -> Result<()> {
match self.current() {
Some((label, _)) => {
Err(format!("Unrecognized child with label '{label}'. Creating AST types from incorrect/incomplete CST nodes is not supported yet."))
Some(edge) => {
Err(format!("Unrecognized child with label '{label}'. Creating AST types from incorrect/incomplete CST nodes is not supported yet.", label = edge.label))
}
None => {
Ok(())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ impl IntoFFI<ffi::Edge> for rust::Edge {
#[inline]
fn _into_ffi(self) -> ffi::Edge {
ffi::Edge {
label: self.label.map(IntoFFI::_into_ffi),
label: self.label._into_ffi(),
node: self.node._into_ffi(),
}
}
Expand Down Expand Up @@ -219,8 +219,8 @@ define_refcell_wrapper! { Cursor {
self._borrow_ffi().node()._into_ffi()
}

fn label(&self) -> Option<ffi::EdgeLabel> {
self._borrow_ffi().label().map(IntoFFI::_into_ffi)
fn label(&self) -> ffi::EdgeLabel {
self._borrow_ffi().label()._into_ffi()
}

fn text_offset(&self) -> ffi::TextIndex {
Expand Down
Loading
Loading