1extern crate perplex;
3
4use std::path::PathBuf;
5use std::fs::File;
6
7use perplex::grammar::{self, Grammar, Rule};
8use perplex::item_set::ItemSets;
9use perplex::machine::StateMachine;
10use perplex::backend::{generate_parser, Backend};
11
12fn main() {
13 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 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 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 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 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 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 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 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 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 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 let is = ItemSets::compute(&g);
116 eprintln!("Perplex Grammar Item Sets:");
117 eprintln!("{}", is.pretty(&g));
118
119 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 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}