utf8/
utf8.rs

1// Example shows basic UTF-8 combinators
2
3use pom::utf8::*;
4
5fn main() {
6	// Informal, Spanish-language movie database format
7	let input = "\
8Título: Abre los ojos
9Año: 1997
10Director: Alejandro Amenábar
11
12Título: Amores Perros
13Director: Alejandro González Iñárritu
14Año: 2000
15
16Título: La montaña sagrada
17Año: 1973
18Director: Alejandro Jodorowsky
19";
20
21	enum DataLine<'a> {
22		Title(&'a str),
23		Director(&'a str),
24		Year(i32),
25	}
26
27	fn positive<'a>() -> Parser<'a, i32> {
28		//		let integer = (one_of("123456789") - one_of("0123456789").repeat(0..)) | sym(b'0'); // TODO
29		let digit = one_of("0123456789");
30		let integer = digit.discard().repeat(1..);
31		integer.collect().convert(|x| x.parse::<i32>())
32	}
33
34	fn rest_str<'a>() -> Parser<'a, &'a str> {
35		any().repeat(1..).collect()
36	}
37
38	fn separator<'a>() -> Parser<'a, ()> {
39		seq(": ").discard()
40	}
41
42	let parser = (seq("Título") * separator() * rest_str().map(|s| DataLine::Title(s)))
43		| (seq("Director") * separator() * rest_str().map(|s| DataLine::Director(s)))
44		| (seq("Año") * separator() * positive().map(|i| DataLine::Year(i)));
45
46	{
47		let mut title_opt: Option<&str> = None;
48		let mut year_opt: Option<i32> = None;
49		let mut director_opt: Option<&str> = None;
50
51		for line in input.lines() {
52			if !line.is_empty() {
53				// Skip blank lines without parsing
54				// Parse line
55				match parser.parse_str(line).unwrap() {
56					DataLine::Title(s) => title_opt = Some(s),
57					DataLine::Director(s) => director_opt = Some(s),
58					DataLine::Year(s) => year_opt = Some(s),
59				}
60				// When all three line types have been collected, print them
61				if let (Some(title), Some(year), Some(director)) =
62					(title_opt, year_opt, director_opt)
63				{
64					println!("Title: {}\nDirector: {}\nYear: {}\n", title, director, year);
65					(title_opt, year_opt, director_opt) = (None, None, None);
66				}
67			}
68		}
69	}
70}