syntax_parser_generator/parsing/translator/
sdt.rs1use std::fmt::Debug;
2
3use crate::handles::{Handle, Handled};
4use crate::handles::collections::{HandledVec, HandleMap};
5use crate::handles::specials::AutomaticallyHandled;
6use crate::lex::Lexeme;
7use crate::parsing::lr_parser::execute::{FinalDecision, LrParserDecision, LrParserExecution};
8use crate::parsing::lr_parser::LrParser;
9use crate::parsing::translator::build::Nonterminal;
10use crate::parsing::translator::handlers::{LeafSatelliteBuilder, SatelliteReducer};
11
12pub struct SyntaxDirectedTranslator<LexemeType: Handled, Context, Satellite> {
22 pub(super) lr_parser: LrParser<LexemeType, Nonterminal, SatelliteReducer<Context, Satellite>>,
23 pub(super) default_leaf_satellite_builder: Option<LeafSatelliteBuilder<Context, Satellite>>,
24 pub(super) leaf_satellite_builder_map:
25 HandleMap<LexemeType, LeafSatelliteBuilder<Context, Satellite>>,
26 pub(super) satellite_reducers: HandledVec<SatelliteReducer<Context, Satellite>>,
27}
28
29impl<LexemeType: Debug, Context, Satellite> SyntaxDirectedTranslator<LexemeType, Context, Satellite>
30where
31 LexemeType: AutomaticallyHandled,
32{
33 pub fn translate(
42 &self,
43 context: &mut Context,
44 stream: impl Iterator<Item=Lexeme<LexemeType>>,
45 ) -> Option<Satellite> {
46 let mut execution = SyntaxDirectedTranslatorExecution::new(self, context);
47 for lexeme in stream {
48 execution.feed(lexeme)?;
49 }
50 execution.finalize()
51 }
52
53 fn build_leaf(
54 &self,
55 context: &mut Context,
56 lexeme: Lexeme<LexemeType>,
57 ) -> (Handle<LexemeType>, Satellite) {
58 let terminal = lexeme.lexeme_type.handle();
59 let builder = if let Some(builder) = self
60 .leaf_satellite_builder_map
61 .get(lexeme.lexeme_type.handle())
62 {
63 builder
64 } else if let Some(builder) = &self.default_leaf_satellite_builder {
65 builder
66 } else {
67 panic!(
68 "Tried to build a leaf satellite for a lexeme type for which no leaf satellite \
69 builder was specified, and no default builder was set"
70 )
71 };
72 (terminal, builder(context, lexeme.contents))
73 }
74
75 fn reduce_satellites(
76 &self,
77 reducer: Handle<SatelliteReducer<Context, Satellite>>,
78 context: &mut Context,
79 satellites: Vec<Satellite>,
80 ) -> Satellite {
81 self.satellite_reducers[reducer](context, satellites)
82 }
83}
84
85struct SyntaxDirectedTranslatorExecution<'a, LexemeType: AutomaticallyHandled, Context, Satellite> {
86 translator: &'a SyntaxDirectedTranslator<LexemeType, Context, Satellite>,
87 context: &'a mut Context,
88 satellite_stack: Vec<Satellite>,
89 lr_parser_execution:
90 LrParserExecution<'a, LexemeType, Nonterminal, SatelliteReducer<Context, Satellite>>,
91}
92
93impl<'a, LexemeType: AutomaticallyHandled + Debug, Context, Satellite>
94SyntaxDirectedTranslatorExecution<'a, LexemeType, Context, Satellite>
95{
96 fn new(
97 translator: &'a SyntaxDirectedTranslator<LexemeType, Context, Satellite>,
98 context: &'a mut Context,
99 ) -> Self {
100 Self {
101 translator,
102 context,
103 satellite_stack: Vec::new(),
104 lr_parser_execution: translator.lr_parser.new_execution(),
105 }
106 }
107
108 fn feed(&mut self, lexeme: Lexeme<LexemeType>) -> Option<()> {
109 let (terminal, satellite) = self.translator.build_leaf(self.context, lexeme);
110 loop {
111 match self.lr_parser_execution.decide(terminal)? {
112 LrParserDecision::Reduce { size, tag } => self.handle_reduce(size, tag)?,
113 LrParserDecision::Shift => {
114 self.satellite_stack.push(satellite);
115 break;
116 }
117 }
118 }
119 Some(())
120 }
121
122 fn finalize(mut self) -> Option<Satellite> {
123 while let FinalDecision::Reduce { size, tag } = self.lr_parser_execution.decide_final()? {
124 self.handle_reduce(size, tag);
125 }
126 self.satellite_stack.pop()
127 }
128
129 fn handle_reduce(
130 &mut self,
131 size: usize,
132 reducer: Handle<SatelliteReducer<Context, Satellite>>,
133 ) -> Option<()> {
134 if self.satellite_stack.len() < size {
135 return None;
137 }
138 let rhs_satellites = self
139 .satellite_stack
140 .drain((self.satellite_stack.len() - size)..)
141 .collect();
142 let lhs_satellite =
143 self.translator
144 .reduce_satellites(reducer, self.context, rhs_satellites);
145 self.satellite_stack.push(lhs_satellite);
146 Some(())
147 }
148}