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