pub fn generate_parser<W: Write>(
into: &mut W,
backend: &Backend,
machine: &StateMachine,
grammar: &Grammar,
) -> Result<()>Expand description
Generate the code for the parser.
Examples found in repository?
examples/tribble1.rs (lines 50-55)
12fn main() {
13 // Build the grammar in David Tribble's example 11.
14 let mut g = Grammar::new();
15 let (ntS, ntA, ntB) = (
16 g.add_nonterminal("S"),
17 g.add_nonterminal("A"),
18 g.add_nonterminal("B"),
19 );
20 let (ta, tb, tc, td, te) = (
21 g.add_terminal("a"),
22 g.add_terminal("b"),
23 g.add_terminal("c"),
24 g.add_terminal("d"),
25 g.add_terminal("e"),
26 );
27 g.add_rule(Rule::new(ntS, vec![ta.into(), ntA.into(), td.into()]));
28 g.add_rule(Rule::new(ntS, vec![ta.into(), ntB.into(), te.into()]));
29 g.add_rule(Rule::new(ntS, vec![tb.into(), ntA.into(), te.into()]));
30 g.add_rule(Rule::new(ntS, vec![tb.into(), ntB.into(), td.into()]));
31 g.add_rule(Rule::new(ntA, vec![tc.into()]));
32 g.add_rule(Rule::new(ntB, vec![tc.into()]));
33
34 // Compute the first sets for the grammar.
35 let is = ItemSets::compute(&g);
36 println!("{}", is.pretty(&g));
37
38 // Generate the parser code.
39 let sm = StateMachine::try_from(&is).unwrap();
40 let mut backend = Backend::new();
41 backend.add_nonterminal(ntS, "NodeS");
42 backend.add_nonterminal(ntA, "NodeA");
43 backend.add_nonterminal(ntB, "NodeB");
44 backend.add_terminal(grammar::END, "Token::Eof");
45 backend.add_terminal(ta, "Token::A");
46 backend.add_terminal(tb, "Token::B");
47 backend.add_terminal(tc, "Token::C");
48 backend.add_terminal(td, "Token::D");
49 backend.add_terminal(te, "Token::E");
50 generate_parser(
51 &mut File::create("tests/generated/tribble1_parser.rs").unwrap(),
52 &backend,
53 &sm,
54 &g,
55 ).unwrap();
56}More examples
examples/update-grammar.rs (line 179)
12fn main() {
13 // Build the grammar for grammars (how meta!).
14 let mut g = Grammar::new();
15
16 let nt_desc = g.add_nonterminal("desc");
17 let nt_item = g.add_nonterminal("item");
18 let nt_token_decl = g.add_nonterminal("token_decl");
19 let nt_token_name = g.add_nonterminal("token_name");
20 let nt_rule_decl = g.add_nonterminal("rule_decl");
21 let nt_rule_list = g.add_nonterminal("rule_list");
22 let nt_variant = g.add_nonterminal("variant");
23 let nt_sequence_or_epsilon = g.add_nonterminal("sequence_or_epsilon");
24 let nt_sequence = g.add_nonterminal("sequence");
25
26 let t_ident = g.add_terminal("IDENT");
27 let t_code = g.add_terminal("CODE");
28 let t_kw_token = g.add_terminal("'token'");
29 let t_kw_epsilon = g.add_terminal("'epsilon'");
30 let t_kw_end = g.add_terminal("'end'");
31 let t_lparen = g.add_terminal("'('");
32 let t_rparen = g.add_terminal("')'");
33 let t_lbrace = g.add_terminal("'{'");
34 let t_rbrace = g.add_terminal("'}'");
35 let t_period = g.add_terminal("'.'");
36 let t_colon = g.add_terminal("':'");
37 let t_comma = g.add_terminal("','");
38 let t_semicolon = g.add_terminal("';'");
39 let t_pipe = g.add_terminal("'|'");
40
41 // desc : desc item | item | desc ';' | ';' ;
42 let r_desc_a = g.add_rule(Rule::new(nt_desc, vec![nt_desc.into(), nt_item.into()]));
43 let r_desc_b = g.add_rule(Rule::new(nt_desc, vec![nt_item.into()]));
44 let r_desc_c = g.add_rule(Rule::new(nt_desc, vec![nt_desc.into(), t_semicolon.into()]));
45 let r_desc_d = g.add_rule(Rule::new(nt_desc, vec![t_semicolon.into()]));
46
47 // item : token_decl | rule_decl ;
48 let r_item_a = g.add_rule(Rule::new(nt_item, vec![nt_token_decl.into()]));
49 let r_item_b = g.add_rule(Rule::new(nt_item, vec![nt_rule_decl.into()]));
50
51 // token_decl : 'token' token_name '(' CODE ')' ';' ;
52 let r_token_decl = g.add_rule(Rule::new(
53 nt_token_decl,
54 vec![
55 t_kw_token.into(),
56 nt_token_name.into(),
57 t_lparen.into(),
58 t_code.into(),
59 t_rparen.into(),
60 t_semicolon.into(),
61 ],
62 ));
63
64 // token_name : IDENT | 'end' ;
65 let r_token_name_a = g.add_rule(Rule::new(nt_token_name, vec![t_ident.into()]));
66 let r_token_name_b = g.add_rule(Rule::new(nt_token_name, vec![t_kw_end.into()]));
67
68 // rule_decl : IDENT '(' CODE ')' '{' rule_list '}' ;
69 let r_rule_decl = g.add_rule(Rule::new(
70 nt_rule_decl,
71 vec![
72 t_ident.into(),
73 t_lparen.into(),
74 t_code.into(),
75 t_rparen.into(),
76 t_lbrace.into(),
77 nt_rule_list.into(),
78 t_rbrace.into(),
79 ],
80 ));
81
82 // rule_list : rule_list variant | variant;
83 let r_rule_list_a = g.add_rule(Rule::new(
84 nt_rule_list,
85 vec![nt_rule_list.into(), nt_variant.into()],
86 ));
87 let r_rule_list_b = g.add_rule(Rule::new(nt_rule_list, vec![nt_variant.into()]));
88
89 // variant : sequence_or_epsilon '(' CODE ')' ';'
90 let r_variant = g.add_rule(Rule::new(
91 nt_variant,
92 vec![
93 nt_sequence_or_epsilon.into(),
94 t_lparen.into(),
95 t_code.into(),
96 t_rparen.into(),
97 t_semicolon.into(),
98 ],
99 ));
100
101 // sequence_or_epsilon : sequence | 'epsilon' ;
102 let r_sequence_or_epsilon_a =
103 g.add_rule(Rule::new(nt_sequence_or_epsilon, vec![nt_sequence.into()]));
104 let r_sequence_or_epsilon_b =
105 g.add_rule(Rule::new(nt_sequence_or_epsilon, vec![t_kw_epsilon.into()]));
106
107 // sequence : sequence IDENT | IDENT ;
108 let r_sequence_a = g.add_rule(Rule::new(
109 nt_sequence,
110 vec![nt_sequence.into(), t_ident.into()],
111 ));
112 let r_sequence_b = g.add_rule(Rule::new(nt_sequence, vec![t_ident.into()]));
113
114 // Compute the item sets for the grammar.
115 let is = ItemSets::compute(&g);
116 eprintln!("Perplex Grammar Item Sets:");
117 eprintln!("{}", is.pretty(&g));
118
119 // Configure the code generation backend.
120 let mut backend = Backend::new();
121
122 backend.add_nonterminal(nt_desc, "ast::Desc");
123 backend.add_nonterminal(nt_item, "ast::Item");
124 backend.add_nonterminal(nt_token_decl, "ast::TokenDecl");
125 backend.add_nonterminal(nt_token_name, "ast::TokenName");
126 backend.add_nonterminal(nt_rule_decl, "ast::RuleDecl");
127 backend.add_nonterminal(nt_rule_list, "Vec<ast::Variant>");
128 backend.add_nonterminal(nt_variant, "ast::Variant");
129 backend.add_nonterminal(nt_sequence_or_epsilon, "Vec<String>");
130 backend.add_nonterminal(nt_sequence, "Vec<String>");
131
132 backend.add_terminal(grammar::END, "None");
133 backend.add_terminal(t_ident, "Some(Token::Ident(_))");
134 backend.add_terminal(t_code, "Some(Token::Code(_))");
135 backend.add_terminal(t_kw_token, "Some(Token::Keyword(Keyword::Token))");
136 backend.add_terminal(t_kw_epsilon, "Some(Token::Keyword(Keyword::Epsilon))");
137 backend.add_terminal(t_kw_end, "Some(Token::Keyword(Keyword::End))");
138 backend.add_terminal(t_lparen, "Some(Token::LParen)");
139 backend.add_terminal(t_rparen, "Some(Token::RParen)");
140 backend.add_terminal(t_lbrace, "Some(Token::LBrace)");
141 backend.add_terminal(t_rbrace, "Some(Token::RBrace)");
142 backend.add_terminal(t_period, "Some(Token::Period)");
143 backend.add_terminal(t_colon, "Some(Token::Colon)");
144 backend.add_terminal(t_comma, "Some(Token::Comma)");
145 backend.add_terminal(t_semicolon, "Some(Token::Semicolon)");
146 backend.add_terminal(t_pipe, "Some(Token::Pipe)");
147
148 backend.add_reduction_function(r_desc_a, "reduce_desc_a");
149 backend.add_reduction_function(r_desc_b, "reduce_desc_b");
150 backend.add_reduction_function(r_desc_c, "reduce_desc_c");
151 backend.add_reduction_function(r_desc_d, "reduce_desc_d");
152 backend.add_reduction_function(r_item_a, "reduce_item_a");
153 backend.add_reduction_function(r_item_b, "reduce_item_b");
154 backend.add_reduction_function(r_token_decl, "reduce_token_decl");
155 backend.add_reduction_function(r_token_name_a, "reduce_token_name_a");
156 backend.add_reduction_function(r_token_name_b, "reduce_token_name_b");
157 backend.add_reduction_function(r_rule_decl, "reduce_rule_decl");
158 backend.add_reduction_function(r_rule_list_a, "reduce_rule_list_a");
159 backend.add_reduction_function(r_rule_list_b, "reduce_rule_list_b");
160 backend.add_reduction_function(r_variant, "reduce_variant");
161 backend.add_reduction_function(r_sequence_or_epsilon_a, "reduce_sequence_or_epsilon_a");
162 backend.add_reduction_function(r_sequence_or_epsilon_b, "reduce_sequence_or_epsilon_b");
163 backend.add_reduction_function(r_sequence_a, "reduce_sequence_a");
164 backend.add_reduction_function(r_sequence_b, "reduce_sequence_b");
165
166 // // Generate the parser code.
167 // let sm = StateMachine::try_from(&is).expect("failed to generate state machine");
168 // let stdout = std::io::stdout();
169 // generate_parser(&mut stdout.lock(), &backend, &sm, &g).expect("failed to generate parser code");
170
171 // Generate the parser code.
172 let mut path = PathBuf::from(file!());
173 path.pop();
174 path.pop();
175 path.push("src");
176 path.push("parser_states.rs");
177 eprintln!("Generating parser code in {:?}", path);
178 let sm = StateMachine::try_from(&is).expect("failed to generate state machine");
179 generate_parser(&mut File::create(path).unwrap(), &backend, &sm, &g)
180 .expect("failed to generate parser code");
181}