I'm struggling to understand how to represent a self-referential structure. Ideally it'd be structured like this:
// A parsed node,
enum Node<'src> {
Parsed(...)
/// Unknown node
Unknown(&'src str)
}
// A group of nodes such as an object within the source
struct Group<'src> {
nodes: &'src[Node<'src>]
}
// Overarching structure
struct Root {
src: String
nodes: Vec<Node<'src>>,
groups: Vec<Group<'src>>
}
fn parse<'src>(src: &'src str) -> Vec<Node<'src>> {...}
fn group<'src>(nodes: &'src[Node]) -> Vec<&'src[Node]> {...}
impl Root {
fn new(src: String) -> Self {
let nodes = parse(&src);
let groups = group(&nodes[..]);
Self {
src,
nodes,
groups,
}
}
}
For context:
My task is to parse a linear-structured language (G-Code), modify some parts and restructure it. One issue I have is I'm unable to fully parse the code as it's very non-standardised but the parts I care about are standardised, therefore provided things go out the same as they went in I'm good e.g.
; Start Block 1
G0 X50 Y20 ; G0 is standard
G0 X10 Y10
; End Block 1
; Start Block 2
G0 X10 Y120
M117 ; M117 isn't, but if it remains in the same position within the block it should be safe
G0 X80 Y10
; Start Block 2
I'd want to perform operations over the G0 commands, and reorder the blocks.
I've written a functioning parser in Nom, however I'm now struggling to fit this together and splitting the parsed file into chunks, Doing things as they are typed results in the compiler saying that both Root::src and Root::nodes don't live long enough when borrowed in parse and group.
Is my current method reasonable or should I structure things differently? How do I prove to the compiler that the underlying data lives long enough?