1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
use std::{error, fmt};
use polytype::Type;
use nom::types::CompleteStr;
use super::{AppliedRule, Grammar, Rule};
#[derive(Clone, Debug)]
pub enum ParseError {
InapplicableRule(Type, String),
NomError(String),
}
impl fmt::Display for ParseError {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match *self {
ParseError::InapplicableRule(ref nt, ref s) => {
write!(f, "invalide rule {} for nonterminal {}", s, nt)
}
ParseError::NomError(ref err) => write!(f, "could not parse: {}", err),
}
}
}
impl error::Error for ParseError {
fn description(&self) -> &str {
"could not parse expression"
}
}
fn location<'a>(
grammar: &'a Grammar,
nt: &Type,
name: &str,
) -> Result<(usize, &'a Rule), ParseError> {
if let Some(rules) = grammar.rules.get(nt) {
rules
.iter()
.enumerate()
.find(|&(_, r)| r.name == name)
.ok_or_else(|| ParseError::InapplicableRule(nt.clone(), String::from(name)))
} else {
Err(ParseError::InapplicableRule(nt.clone(), String::from(name)))
}
}
#[derive(Debug)]
struct Item(String, Vec<Item>);
impl Item {
fn into_applied(self, grammar: &Grammar, nt: Type) -> Result<AppliedRule, ParseError> {
let (loc, r) = location(grammar, &nt, &self.0)?;
if let Some(args) = r.production.args() {
let inner: Result<Vec<AppliedRule>, ParseError> = self.1
.into_iter()
.zip(args)
.map(move |(item, nt)| item.into_applied(grammar, nt.clone()))
.collect();
Ok(AppliedRule(nt, loc, inner?))
} else {
Ok(AppliedRule(nt, loc, vec![]))
}
}
}
fn alphanumeric_ext(c: char) -> bool {
(c >= 0x21 as char && c <= 0x7E as char) && !(c == '(' || c == ')' || c == ',')
}
named!(var<CompleteStr, Item>,
do_parse!(
name: ws!( take_while!(alphanumeric_ext) ) >>
(Item(name.0.to_string(), vec![]))
));
named!(func<CompleteStr, Item>,
do_parse!(
name: ws!( take_while!(alphanumeric_ext) ) >>
args: delimited!(tag!("("), separated_list!(tag!(","), expr), tag!(")")) >>
(Item(name.0.to_string(), args))
));
named!(expr<CompleteStr, Item>, alt!(func | var));
pub fn parse(grammar: &Grammar, input: &str, nt: Type) -> Result<AppliedRule, ParseError> {
match expr(CompleteStr(input)) {
Ok((_, item)) => item.into_applied(grammar, nt),
Err(err) => Err(ParseError::NomError(format!("{:?}", err))),
}
}