1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
// This is a proposed fix for the Extract trait implementation in expansion.rs
//! Proposed fixes for Extract trait implementation using symbol IDs.
// The key insight is that we need to generate code that uses symbol IDs
// rather than heuristics based on child counts and string matching
// For the pure-rust Extract implementation, instead of:
/*
if node.child_count() == 1 {
return #extract_expr;
}
*/
// We should generate:
/*
// The generated parser includes a function to look up symbol names
// We need to match on the actual symbol of the parse tree node
match node.symbol {
// These symbol IDs would be determined at build time
SYMBOL_ID_NUMBER => { /* extract Number variant */ }
SYMBOL_ID_STRING => { /* extract String variant */ }
SYMBOL_ID_IDENTIFIER => { /* extract Identifier variant */ }
_ => panic!("Unknown symbol ID: {}", node.symbol)
}
*/
// The challenge is that at macro expansion time, we don't know the symbol IDs
// So we need to generate code that will work with the build-time generated mappings
// One approach is to generate code like this:
/*
impl Extract<PrimaryExpression> for PrimaryExpression {
fn extract(node: Option<&ParsedNode>, source: &[u8], _last_idx: usize, _leaf_fn: Option<&Self::LeafFn>) -> Self {
let node = node.unwrap();
// Get the actual node (might be wrapped)
let actual_node = if node.children.len() == 1 {
&node.children[0]
} else {
node
};
// Use the symbol name to determine the variant
// The parser generator ensures each variant gets a unique symbol
let symbol_name = actual_node.kind();
match symbol_name {
"number_literal" => Self::Number(NumberLiteral::extract(Some(actual_node), source, _last_idx, None)),
"string_literal" => Self::String(StringLiteral::extract(Some(actual_node), source, _last_idx, None)),
"identifier" => Self::Identifier(Identifier::extract(Some(actual_node), source, _last_idx, None)),
_ => panic!("Unknown symbol name for PrimaryExpression: {}", symbol_name)
}
}
}
*/
// But even better would be to use the symbol IDs directly:
/*
// In the generated parser file, we have:
pub const PRIMARY_EXPRESSION_VARIANTS: &[(&str, u16)] = &[
("Number", 57), // symbol ID for number_literal
("String", 58), // symbol ID for string_literal
("Identifier", 56), // symbol ID for identifier
];
// Then in the Extract impl:
match actual_node.symbol {
57 => Self::Number(...),
58 => Self::String(...),
56 => Self::Identifier(...),
_ => panic!(...)
}
*/