reader.rs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. use regex::{Captures, Regex};
  2. use std::rc::Rc;
  3. use crate::types::MalErr::ErrString;
  4. use crate::types::MalVal::{Bool, Int, List, Nil, Str, Sym, Vector};
  5. use crate::types::{error, hash_map, MalErr, MalRet, MalVal};
  6. #[derive(Debug, Clone)]
  7. struct Reader {
  8. tokens: Vec<String>,
  9. pos: usize,
  10. }
  11. impl Reader {
  12. fn next(&mut self) -> Result<String, MalErr> {
  13. self.pos = self.pos + 1;
  14. Ok(self
  15. .tokens
  16. .get(self.pos - 1)
  17. .ok_or(ErrString("underflow".to_string()))?
  18. .to_string())
  19. }
  20. fn peek(&self) -> Result<String, MalErr> {
  21. Ok(self
  22. .tokens
  23. .get(self.pos)
  24. .ok_or(ErrString("underflow".to_string()))?
  25. .to_string())
  26. }
  27. }
  28. fn tokenize(str: &str) -> Vec<String> {
  29. lazy_static! {
  30. static ref RE: Regex = Regex::new(
  31. r###"[\s,]*(~@|[\[\]{}()'`~^@]|"(?:\\.|[^\\"])*"?|;.*|[^\s\[\]{}('"`,;)]+)"###
  32. )
  33. .unwrap();
  34. }
  35. let mut res = vec![];
  36. for cap in RE.captures_iter(str) {
  37. if cap[1].starts_with(";") {
  38. continue;
  39. }
  40. res.push(String::from(&cap[1]));
  41. }
  42. res
  43. }
  44. fn unescape_str(s: &str) -> String {
  45. lazy_static! {
  46. static ref RE: Regex = Regex::new(r#"\\(.)"#).unwrap();
  47. }
  48. RE.replace_all(&s, |caps: &Captures| {
  49. format!("{}", if &caps[1] == "n" { "\n" } else { &caps[1] })
  50. })
  51. .to_string()
  52. }
  53. fn read_atom(rdr: &mut Reader) -> MalRet {
  54. lazy_static! {
  55. static ref INT_RE: Regex = Regex::new(r"^-?[0-9]+$").unwrap();
  56. static ref STR_RE: Regex = Regex::new(r#""(?:\\.|[^\\"])*""#).unwrap();
  57. }
  58. let token = rdr.next()?;
  59. match &token[..] {
  60. "nil" => Ok(Nil),
  61. "false" => Ok(Bool(false)),
  62. "true" => Ok(Bool(true)),
  63. _ => {
  64. if INT_RE.is_match(&token) {
  65. Ok(Int(token.parse().unwrap()))
  66. } else if STR_RE.is_match(&token) {
  67. Ok(Str(unescape_str(&token[1..token.len() - 1])))
  68. } else if token.starts_with("\"") {
  69. error("expected '\"', got EOF")
  70. } else if token.starts_with(":") {
  71. Ok(Str(format!("\u{29e}{}", &token[1..])))
  72. } else {
  73. Ok(Sym(token.to_string()))
  74. }
  75. }
  76. }
  77. }
  78. fn read_seq(rdr: &mut Reader, end: &str) -> MalRet {
  79. let mut seq: Vec<MalVal> = vec![];
  80. rdr.next()?;
  81. loop {
  82. let token = match rdr.peek() {
  83. Ok(t) => t,
  84. Err(_) => return error(&format!("expected '{}', got EOF", end)),
  85. };
  86. if token == end {
  87. break;
  88. }
  89. seq.push(read_form(rdr)?)
  90. }
  91. let _ = rdr.next();
  92. match end {
  93. ")" => Ok(list!(seq)),
  94. "]" => Ok(vector!(seq)),
  95. "}" => hash_map(seq),
  96. _ => error("read_seq unknown end value"),
  97. }
  98. }
  99. fn read_form(rdr: &mut Reader) -> MalRet {
  100. let token = rdr.peek()?;
  101. match &token[..] {
  102. "'" => {
  103. let _ = rdr.next();
  104. Ok(list![Sym("quote".to_string()), read_form(rdr)?])
  105. }
  106. "`" => {
  107. let _ = rdr.next();
  108. Ok(list![Sym("quasiquote".to_string()), read_form(rdr)?])
  109. }
  110. "~" => {
  111. let _ = rdr.next();
  112. Ok(list![Sym("unquote".to_string()), read_form(rdr)?])
  113. }
  114. "~@" => {
  115. let _ = rdr.next();
  116. Ok(list![Sym("splice-unquote".to_string()), read_form(rdr)?])
  117. }
  118. "^" => {
  119. let _ = rdr.next();
  120. let meta = read_form(rdr)?;
  121. Ok(list![Sym("with-meta".to_string()), read_form(rdr)?, meta])
  122. }
  123. "@" => {
  124. let _ = rdr.next();
  125. Ok(list![Sym("deref".to_string()), read_form(rdr)?])
  126. }
  127. ")" => error("unexpected ')'"),
  128. "(" => read_seq(rdr, ")"),
  129. "]" => error("unexpected ']'"),
  130. "[" => read_seq(rdr, "]"),
  131. "}" => error("unexpected '}'"),
  132. "{" => read_seq(rdr, "}"),
  133. _ => read_atom(rdr),
  134. }
  135. }
  136. pub fn read_str(str: String) -> MalRet {
  137. let tokens = tokenize(&str);
  138. //println!("tokens: {:?}", tokens);
  139. if tokens.len() == 0 {
  140. return error("no input");
  141. }
  142. read_form(&mut Reader {
  143. pos: 0,
  144. tokens: tokens,
  145. })
  146. }