1 use std::iter;
2 
3 use grammar::parse_tree::*;
4 use grammar::pattern::*;
5 use lalrpop_util;
6 use tok;
7 
8 #[cfg(not(feature = "test"))]
9 #[allow(dead_code)]
10 mod lrgrammar;
11 
12 #[cfg(feature = "test")]
13 lalrpop_mod!(
14     #[allow(dead_code)]
15     lrgrammar,
16     "/src/parser/lrgrammar.rs"
17 );
18 
19 #[cfg(test)]
20 mod test;
21 
22 pub enum Top {
23     Grammar(Grammar),
24     Pattern(Pattern<TypeRef>),
25     MatchMapping(TerminalString),
26     TypeRef(TypeRef),
27     GrammarWhereClauses(Vec<WhereClause<TypeRef>>),
28 }
29 
30 pub type ParseError<'input> = lalrpop_util::ParseError<usize, tok::Tok<'input>, tok::Error>;
31 
32 macro_rules! parser {
33     ($input:expr, $offset:expr, $pat:ident, $tok:ident) => {{
34         let input = $input;
35         let tokenizer =
36             iter::once(Ok((0, tok::Tok::$tok, 0))).chain(tok::Tokenizer::new(input, $offset));
37         lrgrammar::TopParser::new()
38             .parse(input, tokenizer)
39             .map(|top| match top {
40                 Top::$pat(x) => x,
41                 _ => unreachable!(),
42             })
43     }};
44 }
45 
parse_grammar<'input>(input: &'input str) -> Result<Grammar, ParseError<'input>>46 pub fn parse_grammar<'input>(input: &'input str) -> Result<Grammar, ParseError<'input>> {
47     let mut grammar = parser!(input, 0, Grammar, StartGrammar)?;
48 
49     // find a unique prefix that does not appear anywhere in the input
50     while input.contains(&grammar.prefix) {
51         grammar.prefix.push('_');
52     }
53 
54     Ok(grammar)
55 }
56 
parse_pattern<'input>( input: &'input str, offset: usize, ) -> Result<Pattern<TypeRef>, ParseError<'input>>57 fn parse_pattern<'input>(
58     input: &'input str,
59     offset: usize,
60 ) -> Result<Pattern<TypeRef>, ParseError<'input>> {
61     parser!(input, offset, Pattern, StartPattern)
62 }
63 
parse_match_mapping<'input>( input: &'input str, offset: usize, ) -> Result<MatchMapping, ParseError<'input>>64 fn parse_match_mapping<'input>(
65     input: &'input str,
66     offset: usize,
67 ) -> Result<MatchMapping, ParseError<'input>> {
68     parser!(input, offset, MatchMapping, StartMatchMapping)
69 }
70 
71 #[cfg(test)]
parse_type_ref<'input>(input: &'input str) -> Result<TypeRef, ParseError<'input>>72 pub fn parse_type_ref<'input>(input: &'input str) -> Result<TypeRef, ParseError<'input>> {
73     parser!(input, 0, TypeRef, StartTypeRef)
74 }
75 
76 #[cfg(test)]
parse_where_clauses<'input>( input: &'input str, ) -> Result<Vec<WhereClause<TypeRef>>, ParseError<'input>>77 pub fn parse_where_clauses<'input>(
78     input: &'input str,
79 ) -> Result<Vec<WhereClause<TypeRef>>, ParseError<'input>> {
80     parser!(input, 0, GrammarWhereClauses, StartGrammarWhereClauses)
81 }
82