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}