adnot.rs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. use std::collections::HashMap;
  2. use std::iter::Peekable;
  3. use std::str::{Chars,FromStr};
  4. #[derive(Clone,Debug,PartialEq)]
  5. pub enum Adnot {
  6. Sum(String, Vec<Adnot>),
  7. Prod(HashMap<String, Adnot>),
  8. List(Vec<Adnot>),
  9. Str(String),
  10. Sym(String),
  11. Num(i64),
  12. Dbl(f64),
  13. }
  14. #[derive(Debug)]
  15. pub struct AdnotError {
  16. message: String,
  17. }
  18. type Stream<'a> = Peekable<Chars<'a>>;
  19. fn fail<T>(s: &str) -> Result<T, AdnotError> {
  20. Err(AdnotError { message: s.to_string()})
  21. }
  22. fn parse_val(s: &mut Stream) -> Result<Adnot, AdnotError> {
  23. if let Some(c) = s.next() {
  24. match c {
  25. '[' => parse_list(s),
  26. '(' => parse_sum(s),
  27. '{' => parse_prod(s),
  28. '"' => parse_string(s),
  29. _ if c.is_digit(10) || c == '-' => parse_num(c, s),
  30. _ if c.is_alphabetic() =>
  31. Ok(Adnot::Sym(try!(parse_sym(c, s)))),
  32. _ => fail(&format!("Invalid character: {:?}", c)),
  33. }
  34. } else {
  35. fail("Unexpected end of input")
  36. }
  37. }
  38. fn parse_list(s: &mut Stream) -> Result<Adnot, AdnotError> {
  39. let mut vec = vec![];
  40. loop {
  41. skip_space(s);
  42. if let Some(&']') = s.peek() {
  43. s.next();
  44. return Ok(Adnot::List(vec));
  45. } else {
  46. vec.push(try!(parse_val(s)));
  47. }
  48. }
  49. }
  50. fn parse_sum(s: &mut Stream) -> Result<Adnot, AdnotError> {
  51. let mut vec = vec![];
  52. skip_space(s);
  53. let first = match s.next() {
  54. Some(c) if c.is_alphabetic() => c,
  55. Some(_) => { return fail("Expected a tagname character") }
  56. None => { return fail("Unexpected end of input") }
  57. };
  58. let name = try!(parse_sym(first, s));
  59. loop {
  60. skip_space(s);
  61. if let Some(&')') = s.peek() {
  62. s.next();
  63. return Ok(Adnot::Sum(name, vec));
  64. } else {
  65. vec.push(try!(parse_val(s)));
  66. }
  67. }
  68. }
  69. fn parse_prod(s: &mut Stream) -> Result<Adnot, AdnotError> {
  70. let mut map = HashMap::new();
  71. loop {
  72. skip_space(s);
  73. if let Some(&'}') = s.peek() {
  74. s.next();
  75. return Ok(Adnot::Prod(map));
  76. } else {
  77. skip_space(s);
  78. let first = match s.next() {
  79. Some(c) if c.is_alphabetic() => c,
  80. Some(_) => { return fail("Expected a tagname character") }
  81. None => { return fail("Unexpected end of input") }
  82. };
  83. let key = try!(parse_sym(first, s));
  84. skip_space(s);
  85. let val = try!(parse_val(s));
  86. map.insert(key, val);
  87. }
  88. }
  89. }
  90. fn parse_string(s: &mut Stream) -> Result<Adnot, AdnotError> {
  91. let mut chars = Vec::new();
  92. while let Some(c) = s.next() {
  93. if c == '"' {
  94. break;
  95. } else if c == '\\' {
  96. match s.next() {
  97. Some('n') => chars.push('\n'),
  98. Some('r') => chars.push('\r'),
  99. Some('t') => chars.push('\t'),
  100. Some('\'') => chars.push('\''),
  101. Some('\"') => chars.push('\"'),
  102. Some('\\') => chars.push('\\'),
  103. _ => return fail("Invalid escape sequence"),
  104. }
  105. } else {
  106. chars.push(c);
  107. }
  108. };
  109. Ok(Adnot::Str(chars.iter().cloned().collect()))
  110. }
  111. fn parse_num(c: char, s: &mut Stream) -> Result<Adnot, AdnotError> {
  112. let mut str = vec![c];
  113. str.extend(s.take_while(|c| c.is_digit(10)));
  114. let string: String = str.iter().cloned().collect();
  115. Ok(Adnot::Num(i64::from_str(&string).unwrap()))
  116. }
  117. fn parse_sym(c: char, s: &mut Stream) -> Result<String, AdnotError> {
  118. let mut chars = vec![c];
  119. while let Some(&c) = s.peek() {
  120. if c.is_alphanumeric() || c == '_' {
  121. chars.push(s.next().unwrap());
  122. } else {
  123. break;
  124. }
  125. };
  126. Ok(chars.iter().cloned().collect())
  127. }
  128. fn skip_space(s: &mut Stream) {
  129. while let Some(&c) = s.peek() {
  130. match c {
  131. '#' => { skip_comment(s); }
  132. _ if c.is_whitespace() => { s.next(); }
  133. _ => break,
  134. }
  135. }
  136. }
  137. fn skip_comment(s: &mut Stream) {
  138. s.next();
  139. while let Some(&c) = s.peek() {
  140. if c == '\n' || c == '\r' {
  141. s.next();
  142. return;
  143. } else {
  144. s.next();
  145. }
  146. }
  147. }
  148. impl Adnot {
  149. pub fn parse(s: &str) -> Result<Adnot, AdnotError> {
  150. let mut stream = s.chars().peekable();
  151. skip_space(&mut stream);
  152. parse_val(&mut stream)
  153. }
  154. }