update_grammar/
update-grammar.rs

1// Copyright (c) 2018 Fabian Schuiki
2extern 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    // 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}