topdown/
lib.rs

1#![crate_type = "rlib"]
2#![crate_type = "dylib"]
3extern crate regex;
4
5pub use self::ParserResult::{Succ, Fail, Error};
6use std::cmp::{min, Ordering};
7use std::fmt;
8
9pub use re::re;
10pub use chainl::chainl;
11pub use chainr::chainr;
12pub use choice::choice;
13pub use until::until;
14pub use many::many;
15pub use many1::many1;
16pub use keyword::keyword;
17pub use try::try;
18pub use skip::skip;
19pub use cond::cond;
20pub use opt::opt;
21pub use wrapper::wrap;
22pub use split::split;
23pub use many_until::many_until;
24
25pub mod re;
26pub mod chainl;
27pub mod chainr;
28pub mod choice;
29pub mod until;
30pub mod many;
31pub mod many1;
32pub mod keyword;
33pub mod try;
34pub mod skip;
35pub mod cond;
36pub mod opt;
37pub mod wrapper;
38pub mod split;
39pub mod many_until;
40mod macros;
41
42
43pub struct CharSeq<'a> {
44    pub pos: usize,
45    pub text: String,
46    pub place: String,
47    hooks: Vec<&'a (ParserHook+'a)>,
48    pub enable_hook: bool,
49    pub trace: bool
50}
51
52#[derive(Clone)]
53pub struct LocationInfo {
54    pub col: usize,
55    pub row: usize,
56    pub pos: usize,
57    pub place: String
58}
59
60impl Ord for LocationInfo {
61    fn cmp(&self, other: &LocationInfo) -> Ordering {
62        if self.row == other.row {
63            self.col.cmp(&other.col)
64        } else {
65            self.row.cmp(&other.row)
66        }
67    }
68}
69
70impl PartialOrd for LocationInfo {
71    fn partial_cmp(&self, other: &LocationInfo) -> Option<Ordering> {
72        Some(self.pos.cmp(&other.pos))
73    }
74    fn lt(&self, other: &LocationInfo) -> bool {
75        self.pos < other.pos
76    }
77    fn le(&self, other: &LocationInfo) -> bool {
78        self.pos <= other.pos
79    }
80    fn gt(&self, other: &LocationInfo) -> bool {
81        self.pos > other.pos
82    }
83    fn ge(&self, other: &LocationInfo) -> bool {
84        self.pos >= other.pos
85    }
86}
87
88
89impl PartialEq for LocationInfo {
90    fn eq(&self, other: &LocationInfo) -> bool {
91        self.pos == other.pos
92    }
93}
94
95impl Eq for LocationInfo {
96}
97
98impl fmt::Display for LocationInfo {
99    fn fmt(&self, f:&mut fmt::Formatter) -> fmt::Result {
100        f.write_str(format!("Col: {}, Row: {} at {}", self.col, self.row, self.place).as_str())
101    }
102}
103
104pub enum ParserResult<T> {
105    Succ(T),
106    Error(String, LocationInfo),
107    Fail(String, LocationInfo),
108}
109
110impl<T> ParserResult<T> {
111    pub fn map<S, F>(self, f: F) -> ParserResult<S> where F: Fn(T) -> S {
112        match self {
113            Succ(c) => Succ(f(c)),
114            Fail(m, l) => Fail(m.clone(), l.clone()),
115            Error(m, l) => Error(m.clone(), l.clone())
116        }
117    }
118
119    pub fn and_then<S, F>(self, mut f: F) -> ParserResult<S> where F: FnMut(T) -> ParserResult<S> {
120        match self {
121            Succ(c) => f(c),
122            Fail(m, l) => Fail(m.clone(), l.clone()),
123            Error(m, l) => Error(m.clone(), l.clone())
124        }
125    }
126}
127
128impl<'a> CharSeq<'a> {
129    pub fn view(&self) -> &str {
130        return &self.text[self.pos..];
131    }
132
133    pub fn eof(&self) -> bool {
134        return self.text.len() <= self.pos;
135    }
136
137    pub fn new(t: &str, l: &str) -> CharSeq<'a> {
138        return CharSeq{pos: 0, text: t.to_string(), place: l.to_string(), hooks: Vec::new(), enable_hook: true, trace: false};
139    }
140
141    pub fn fail<T>(&self, msg: &str) -> ParserResult<T> {
142        return Fail(msg.to_string(), self.get_location());
143    }
144
145    pub fn get_location(&self) -> LocationInfo {
146        let mut col = 1;
147        let mut row = 1;
148        let max = self.pos;
149        let mut i = 0;
150        for c in self.text.chars() {
151            if i >= max {
152                break;
153            }
154            col += 1;
155            if c == '\n' {
156                row += 1;
157                col = 1;
158            }
159            i+=1;
160        }
161        return LocationInfo{col: col, row:row, pos: self.pos, place: self.place.clone()};
162    }
163
164    pub fn current(&self) -> char {
165        if self.eof() {
166            return '\0';
167        } else {
168            return self.text.chars().nth(self.pos).unwrap();
169        }
170    }
171
172    pub fn next(&mut self) {
173        if !self.eof() {
174            self.pos += 1;
175        }
176    }
177
178    pub fn add_hook(&mut self, hook: &'a (ParserHook+'a)) {
179        self.hooks.push(hook);
180    }
181
182    #[allow(unused_variables)]
183    pub fn do_hook(&mut self) {
184        if !self.enable_hook {
185            return ();
186        }
187        self.enable_hook = false;
188        for h in self.hooks.clone().iter() {
189            h.hook(self);
190        }
191        self.enable_hook = true;
192        return ();
193    }
194
195    pub fn accept<T>(&mut self, p: &Parser<T>) -> ParserResult<T> {
196        if self.trace {
197            println!("{}", self.get_location());
198        }
199        return p.parse(self);
200    }
201}
202
203
204pub trait Parser<T> {
205    fn parse(&self, cs: &mut CharSeq) -> ParserResult<T> {
206        cs.do_hook();
207        let r = self._parse(cs);
208        cs.do_hook();
209        return r;
210    }
211
212    fn _parse(&self, cs: &mut CharSeq) -> ParserResult<T>;
213    
214    #[allow(unused_variables)]
215    fn lookahead(&self, cs: &mut CharSeq) -> bool {
216        let p = cs.pos;
217        let result = match self.parse(cs) {
218            Succ(c) => true,
219            Fail(m, l) => false,
220            Error(m, l) => false
221        };
222        cs.pos = p;
223        return result;
224    }
225}
226
227pub trait ParserHook {
228    fn hook(&self, cs: &mut CharSeq);
229}
230
231impl<'a> Parser<String> for &'a str {
232    fn _parse(&self, cs: &mut CharSeq) -> ParserResult<String> {
233        if cs.view()[..min(self.len(), cs.view().len())] == **self {
234            cs.pos = cs.pos + self.len();
235            return Succ(self.to_string().clone());
236        } else {
237            return cs.fail(*self);
238        }
239    }
240}
241
242#[derive(Clone)]
243pub struct EOF;
244
245impl Parser<()> for EOF {
246    fn _parse(&self, cs: &mut CharSeq) -> ParserResult<()> {
247        if cs.eof() {
248            Succ(())
249        } else {
250            cs.fail("not eof")
251        }
252    }
253}
254
255
256#[cfg(test)]
257#[allow(unused_variables)]
258#[allow(unused_imports)]
259mod tests {
260    use super::{CharSeq, ParserResult, Parser, Succ, Fail, Error};
261    #[test]
262    fn test_s1() {
263        let mut cs = CharSeq::new("abcabcdef", "<mem>");
264        assert!(cs.pos == 0);
265        match cs.accept(&"abc") {
266            Succ(a) => assert!(a == "abc"),
267            _ => assert!(false, "bug")
268        }
269        assert!(cs.pos == 3);
270        assert!(cs.view() == "abcdef");
271
272        match cs.accept(&"abc") {
273            Succ(a) => assert!(a == "abc"),
274            _ => assert!(false, "bug")
275        }
276        assert!(cs.pos == 6);
277        assert!(cs.view() == "def");
278        
279        match cs.accept(&"abc") {
280            Succ(a) => assert!(false, format!("unexcepted result: {}, pos:{}", a, cs.pos)),
281            Fail(a, b) => (),
282            Error(a, b) => assert!(false, "error")
283        }
284        assert!(cs.pos == 6);
285     
286        match cs.accept(&"def") {
287            Succ(a) => assert!(a=="def"),
288            _ => assert!(false, "bug")
289        }
290        assert!(cs.pos == 9);
291        assert!(cs.eof());
292
293        match cs.accept(&"def") {
294            Succ(a) => assert!(false, format!("unexcepted result: {}, pos: {}", a , cs.pos)),
295            Fail(a, b) => (),
296            Error(a, b) => assert!(false, "error")
297        }
298        assert!(cs.pos == 9);
299        assert!(cs.eof());
300    }
301
302    #[test]
303    fn test_s2() {
304        let mut cs = CharSeq::new("abcdefghi", "<mem>");
305        let r = cs.accept(&"abc").and_then(
306            |a| cs.accept(&"def").and_then(
307                |b| cs.accept(&"ghi").map(
308                    |c| {
309                        assert!(a == "abc");
310                        assert!(b == "def");
311                        assert!(c == "ghi");
312                    }
313                )
314            )
315        );
316    }
317
318    #[test]
319    fn test_s3() {
320        let mut cs = CharSeq::new("a", "<mem>");
321        match cs.accept(&"abc") {
322            Succ(a) => assert!(false, format!("unexcepted result: {}, pos: {}", a , cs.pos)),
323            Fail(a, b) => (),
324            Error(a, b) => assert!(false, "error")
325        }
326    }
327}