do_not_use_antlr_rust/prediction_mode.rs
1use std::collections::HashMap;
2
3use bit_set::BitSet;
4
5use crate::atn::INVALID_ALT;
6use crate::atn_config::ATNConfig;
7use crate::atn_config_set::ATNConfigSet;
8use crate::atn_state::ATNStateRef;
9use crate::prediction_context::PredictionContext;
10use crate::semantic_context::SemanticContext;
11
12/// This enum defines the prediction modes available in ANTLR 4 along with
13/// utility methods for analyzing configuration sets for conflicts and/or
14/// ambiguities.
15///
16/// It is set through `ParserATNSimulator::
17#[allow(non_camel_case_types)]
18#[derive(Eq, PartialEq, Copy, Clone, Debug)]
19pub enum PredictionMode {
20 /// The SLL(*) prediction mode. This prediction mode ignores the current
21 /// parser context when making predictions. This is the fastest prediction
22 /// mode, and provides correct results for many grammars. This prediction
23 /// mode is more powerful than the prediction mode provided by ANTLR 3, but
24 /// may result in syntax errors for grammar and input combinations which are
25 /// not SLL.
26 ///
27 /// <p>
28 /// When using this prediction mode, the parser will either return a correct
29 /// parse tree (i.e. the same parse tree that would be returned with the
30 /// {@link #LL} prediction mode), or it will report a syntax error. If a
31 /// syntax error is encountered when using the {@link #SLL} prediction mode,
32 /// it may be due to either an actual syntax error in the input or indicate
33 /// that the particular combination of grammar and input requires the more
34 /// powerful {@link #LL} prediction abilities to complete successfully.</p>
35 ///
36 /// <p>
37 /// This prediction mode does not provide any guarantees for prediction
38 /// behavior for syntactically-incorrect inputs.</p>
39 ///
40 SLL = 0,
41 ///
42 /// The LL(*) prediction mode. This prediction mode allows the current parser
43 /// context to be used for resolving SLL conflicts that occur during
44 /// prediction. This is the fastest prediction mode that guarantees correct
45 /// parse results for all combinations of grammars with syntactically correct
46 /// inputs.
47 ///
48 /// <p>
49 /// When using this prediction mode, the parser will make correct decisions
50 /// for all syntactically-correct grammar and input combinations. However, in
51 /// cases where the grammar is truly ambiguous this prediction mode might not
52 /// report a precise answer for <em>exactly which</em> alternatives are
53 /// ambiguous.</p>
54 ///
55 /// <p>
56 /// This prediction mode does not provide any guarantees for prediction
57 /// behavior for syntactically-incorrect inputs.</p>
58 ///
59 LL,
60 ///
61 /// The LL(*) prediction mode with exact ambiguity detection. In addition to
62 /// the correctness guarantees provided by the {@link #LL} prediction mode,
63 /// this prediction mode instructs the prediction algorithm to determine the
64 /// complete and exact set of ambiguous alternatives for every ambiguous
65 /// decision encountered while parsing.
66 ///
67 /// <p>
68 /// This prediction mode may be used for diagnosing ambiguities during
69 /// grammar development. Due to the performance overhead of calculating sets
70 /// of ambiguous alternatives, this prediction mode should be avoided when
71 /// the exact results are not necessary.</p>
72 ///
73 /// <p>
74 /// This prediction mode does not provide any guarantees for prediction
75 /// behavior for syntactically-incorrect inputs.</p>
76 ///
77 LL_EXACT_AMBIG_DETECTION,
78}
79
80impl PredictionMode {
81 //todo move everything here
82}
83
84//
85//
86pub(crate) fn has_sll_conflict_terminating_prediction(
87 mode: PredictionMode,
88 configs: &ATNConfigSet,
89) -> bool {
90 // if all_configs_in_rule_stop_states(configs) {
91 // return true checked outside
92 // }
93 let mut dup = ATNConfigSet::new_base_atnconfig_set(true);
94 let mut configs = &*configs;
95 if mode == PredictionMode::SLL {
96 if configs.has_semantic_context() {
97 configs.get_items().for_each(|it| {
98 let c = ATNConfig::new_with_semantic(
99 it.get_state(),
100 it.get_alt(),
101 it.get_context().cloned(),
102 Box::new(SemanticContext::NONE),
103 );
104 dup.add(Box::new(c));
105 });
106 configs = &dup;
107 }
108 }
109
110 let altsets = get_conflicting_alt_subsets(&configs);
111 let heuristic =
112 has_conflicting_alt_set(&altsets) && !has_state_associated_with_one_alt(&configs);
113 return heuristic;
114}
115
116//fn all_configs_in_rule_stop_states(configs: &ATNConfigSet) -> bool {
117// for co
118//}
119
120pub(crate) fn resolves_to_just_one_viable_alt(altsets: &Vec<BitSet>) -> isize {
121 get_single_viable_alt(altsets)
122}
123
124pub(crate) fn all_subsets_conflict(altsets: &Vec<BitSet>) -> bool {
125 !has_non_conflicting_alt_set(altsets)
126}
127
128pub(crate) fn all_subsets_equal(altsets: &Vec<BitSet>) -> bool {
129 let mut iter = altsets.iter();
130 let first = iter.next();
131 iter.all(|it| it == first.unwrap())
132}
133
134fn has_non_conflicting_alt_set(altsets: &Vec<BitSet>) -> bool {
135 altsets.iter().any(|it| it.len() == 1)
136}
137
138fn has_conflicting_alt_set(altsets: &Vec<BitSet>) -> bool {
139 for alts in altsets {
140 if alts.len() > 1 {
141 return true;
142 }
143 }
144 false
145}
146
147//fn get_unique_alt(altsets: &Vec<BitSet>) -> int { unimplemented!() }
148//
149pub(crate) fn get_alts(altsets: &Vec<BitSet>) -> BitSet {
150 altsets.iter().fold(BitSet::new(), |mut acc, it| {
151 acc.extend(it);
152 acc
153 })
154}
155
156//
157pub(crate) fn get_conflicting_alt_subsets(configs: &ATNConfigSet) -> Vec<BitSet> {
158 let mut configs_to_alts: HashMap<(ATNStateRef, &PredictionContext), BitSet> = HashMap::new();
159 for c in configs.get_items() {
160 let alts = configs_to_alts
161 .entry((c.get_state(), c.get_context().unwrap()))
162 .or_default();
163
164 alts.insert(c.get_alt() as usize);
165 }
166 configs_to_alts.drain().map(|(_, x)| x).collect()
167}
168
169fn get_state_to_alt_map(configs: &ATNConfigSet) -> HashMap<ATNStateRef, BitSet> {
170 let mut m = HashMap::new();
171 for c in configs.get_items() {
172 let alts = m.entry(c.get_state()).or_insert(BitSet::new());
173 alts.insert(c.get_alt() as usize);
174 }
175 m
176}
177
178fn has_state_associated_with_one_alt(configs: &ATNConfigSet) -> bool {
179 let x = get_state_to_alt_map(configs);
180 for alts in x.values() {
181 if alts.len() == 1 {
182 return true;
183 }
184 }
185 false
186}
187
188pub(crate) fn get_single_viable_alt(altsets: &Vec<BitSet>) -> isize {
189 let mut viable_alts = BitSet::new();
190 let mut min_alt = INVALID_ALT as usize;
191 for alt in altsets {
192 min_alt = alt.iter().next().unwrap();
193 viable_alts.insert(min_alt);
194 if viable_alts.len() > 1 {
195 return INVALID_ALT;
196 }
197 }
198 min_alt as isize
199}