metrale_grammar/grammar/functor/
constructor.rs1use crate::grammar::builder::{GrammarBuilder, TagDispatchSpec};
11use crate::grammar::data::GrammarData;
12use crate::grammar::expr::GrammarExprType;
13
14pub fn add_sub_grammar(builder: &mut GrammarBuilder, sub_grammar: &GrammarData) -> i32 {
18 let num_rules = sub_grammar.num_rules();
19 let mut new_ids: Vec<i32> = Vec::with_capacity(num_rules as usize);
20 for i in 0..num_rules {
21 let hint = builder.get_new_rule_name(&sub_grammar.rule(i).name);
22 new_ids.push(builder.add_empty_rule(hint).expect("unique name"));
23 }
24 for i in 0..num_rules {
25 let rule = sub_grammar.rule(i);
26 let new_body = copy_expr(builder, sub_grammar, rule.body_expr_id, &new_ids);
27 builder
28 .update_rule_body(new_ids[i as usize], new_body)
29 .expect("range");
30 let new_la = if rule.lookahead_assertion_id == -1 {
31 -1
32 } else {
33 copy_expr(builder, sub_grammar, rule.lookahead_assertion_id, &new_ids)
34 };
35 builder
36 .update_lookahead_assertion(new_ids[i as usize], new_la)
37 .expect("range");
38 }
39 new_ids[sub_grammar.root_rule_id() as usize]
40}
41
42fn copy_expr(builder: &mut GrammarBuilder, src: &GrammarData, expr_id: i32, id_map: &[i32]) -> i32 {
45 let e = src.expr(expr_id);
46 match e.kind {
47 GrammarExprType::RuleRef => builder.add_rule_ref(id_map[e.data[0] as usize]),
48 GrammarExprType::Repeat => {
49 builder.add_repeat(id_map[e.data[0] as usize], e.data[1], e.data[2])
50 }
51 GrammarExprType::TagDispatch => {
52 let td = src.tag_dispatch(expr_id);
53 let spec = TagDispatchSpec {
54 tag_rule_pairs: td
55 .tag_rule_pairs
56 .iter()
57 .map(|(t, r)| (t.clone(), id_map[*r as usize]))
58 .collect(),
59 stop_eos: td.stop_eos,
60 stop_str: td.stop_str,
61 loop_after_dispatch: td.loop_after_dispatch,
62 excluded_str: td.excluded_str,
63 };
64 builder.add_tag_dispatch(&spec)
65 }
66 GrammarExprType::Sequence => {
67 let ids: Vec<i32> = e
68 .data
69 .iter()
70 .map(|&c| copy_expr(builder, src, c, id_map))
71 .collect();
72 builder.add_sequence(&ids)
73 }
74 GrammarExprType::Choices => {
75 let ids: Vec<i32> = e
76 .data
77 .iter()
78 .map(|&c| copy_expr(builder, src, c, id_map))
79 .collect();
80 builder.add_choices(&ids)
81 }
82 _ => builder.add_grammar_expr(e.kind, e.data),
83 }
84}
85
86pub struct GrammarUnion;
88
89impl GrammarUnion {
90 pub fn apply(grammars: &[GrammarData]) -> GrammarData {
92 let mut builder = GrammarBuilder::new();
93 let root_id = builder.add_empty_rule("root").expect("root");
94 let mut choices: Vec<i32> = Vec::with_capacity(grammars.len());
95 for g in grammars {
96 let sub_root = add_sub_grammar(&mut builder, g);
97 let rr = builder.add_rule_ref(sub_root);
98 let seq = builder.add_sequence(&[rr]);
99 choices.push(seq);
100 }
101 let body = builder.add_choices(&choices);
102 builder.update_rule_body(root_id, body).expect("root range");
103 builder.get_by_id(root_id).expect("root")
104 }
105}
106
107pub struct GrammarConcat;
109
110impl GrammarConcat {
111 pub fn apply(grammars: &[GrammarData]) -> GrammarData {
113 let mut builder = GrammarBuilder::new();
114 let root_id = builder.add_empty_rule("root").expect("root");
115 let mut seq: Vec<i32> = Vec::with_capacity(grammars.len());
116 for g in grammars {
117 let sub_root = add_sub_grammar(&mut builder, g);
118 seq.push(builder.add_rule_ref(sub_root));
119 }
120 let seq_id = builder.add_sequence(&seq);
121 let body = builder.add_choices(&[seq_id]);
122 builder.update_rule_body(root_id, body).expect("root range");
123 builder.get_by_id(root_id).expect("root")
124 }
125}
126
127#[cfg(test)]
128mod tests {
129 use super::*;
130 use crate::grammar::functor::normalizer::GrammarNormalizer;
131 use crate::grammar::parse_ebnf_default;
132
133 fn g(ebnf: &str) -> GrammarData {
134 GrammarNormalizer::apply(parse_ebnf_default(ebnf).expect("parse"))
135 }
136
137 #[test]
138 fn union_of_two_grammars() {
139 let a = g("root ::= \"a\"\n");
140 let b = g("root ::= \"b\"\n");
141 let u = GrammarUnion::apply(&[a, b]);
142 assert_eq!(u.root_rule().name, "root");
143 assert!(u.num_rules() >= 3);
144 }
145
146 #[test]
147 fn concat_of_two_grammars() {
148 let a = g("root ::= \"a\"\n");
149 let b = g("root ::= \"b\"\n");
150 let c = GrammarConcat::apply(&[a, b]);
151 assert_eq!(c.root_rule().name, "root");
152 assert!(c.num_rules() >= 3);
153 }
154
155 #[test]
156 fn sub_grammar_adder_remaps_refs() {
157 let mut builder = GrammarBuilder::new();
158 let sub = g("root ::= inner\ninner ::= \"x\"\n");
159 let root = add_sub_grammar(&mut builder, &sub);
160 let result = builder.get_by_id(root).expect("get");
161 assert_eq!(result.num_rules(), 2);
162 }
163
164 #[test]
165 fn union_single_grammar() {
166 let a = g("root ::= \"only\"\n");
167 let u = GrammarUnion::apply(std::slice::from_ref(&a));
168 assert_eq!(u.root_rule().name, "root");
169 }
170}