symbolic_expressions/
parser.rs1use error::SexpError;
4use Sexp;
5use parse_error;
6use std::io;
7use std::fs::File;
8use std::io::prelude::*;
9
10#[derive(Default)]
11struct Parser {
12 data: Vec<char>,
13 position: usize,
14 line: usize,
15 line_position: usize,
16}
17
18impl Parser {
19 fn peek(&self) -> Result<char, SexpError> {
20 self.fail_on_eof()?;
21 Ok(self.data[self.position])
22 }
23
24 fn get(&mut self) -> Result<char, SexpError> {
25 self.fail_on_eof()?;
26 let c = self.data[self.position];
27 self.position += 1;
28 self.line_position += 1;
29 if c == '\n' {
30 self.line += 1;
31 self.line_position = 0;
32 }
33 Ok(c)
34 }
35
36 fn inc(&mut self) {
37 let c = self.data[self.position];
38 self.position += 1;
39 self.line_position += 1;
40 if c == '\n' {
41 self.line += 1;
42 self.line_position = 0;
43 }
44 }
45
46 fn eat_space(&mut self) {
47 while !self.eof() {
48 let c = self.data[self.position];
49 if c == ' ' || c == '\t' {
50 self.inc();
51 continue;
52 }
53 break;
54 }
55 }
56
57 fn eat_char(&mut self, c: char) -> Result<(), SexpError> {
58 let c2 = self.get()?;
59 if c != c2 {
60 self.parse_error(&format!("expected {} got {}", c, c2))
61 } else {
62 Ok(())
63 }
64 }
65
66 fn eof(&self) -> bool {
67 self.position >= self.data.len()
68 }
69
70 fn fail_on_eof(&self) -> Result<(), SexpError> {
71 if self.eof() {
72 return self.parse_error("End of file reached");
73 }
74 Ok(())
75 }
76
77 fn parse_error<T>(&self, msg: &str) -> Result<T, SexpError> {
78 parse_error(self.line + 1, self.line_position + 1, msg.to_string())
79 }
80}
81
82pub fn parse_str(sexp: &str) -> Result<Sexp, SexpError> {
84 if sexp.is_empty() {
85 return Ok(Sexp::default());
86 }
87 let mut parser = Parser::default();
88 parser.data = sexp.chars().collect();
89 parse(&mut parser)
90}
91
92fn parse(parser: &mut Parser) -> Result<Sexp, SexpError> {
93 parser.eat_space();
94 let c = parser.peek()?;
95 if c == '(' {
96 parse_list(parser)
97 } else if c == '"' {
98 parse_quoted_string(parser)
99 } else if c == ')' {
100 parser.parse_error("Unexpected )")
101 } else {
102 parse_bare_string(parser)
103 }
104}
105
106fn parse_list(parser: &mut Parser) -> Result<Sexp, SexpError> {
107 parser.eat_char('(')?;
108 let mut v = vec![];
109 while !parser.eof() {
110 let c = parser.peek()?;
111 if c == ')' {
112 break;
113 } else if c == ' ' || c == '\t' || c == '\r' || c == '\n' {
114 parser.inc()
115 } else {
116 let s = parse(parser)?;
117 v.push(s)
118 }
119 }
120 parser.eat_char(')')?;
121 parser.eat_space();
122 Ok(Sexp::List(v))
123}
124
125fn parse_quoted_string(parser: &mut Parser) -> Result<Sexp, SexpError> {
126 let mut s = String::new();
127 parser.eat_char('"')?;
128 let mut escape = false;
130 while !parser.eof() {
131 let c = parser.peek()?;
132 if c == '\\' {
133 escape = true;
134 } else if c == '"' {
135 if !escape {
136 break;
137 } else {
138 escape = false;
139 }
140 } else {
141 escape = false;
142 }
143 s.push(c);
144 parser.inc()
145 }
146 parser.eat_char('"')?;
147 Ok(Sexp::String(s))
148}
149
150fn parse_bare_string(parser: &mut Parser) -> Result<Sexp, SexpError> {
151 let mut s = String::new();
152 while !parser.eof() {
153 let c = parser.peek()?;
154 if c == ' ' || c == '(' || c == ')' || c == '\r' || c == '\n' {
155 break;
156 }
157 s.push(c);
158 parser.inc()
159 }
160 Ok(Sexp::String(s))
161}
162
163fn read_file(name: &str) -> Result<String, io::Error> {
164 let mut f = File::open(name)?;
165 let mut s = String::new();
166 f.read_to_string(&mut s)?;
167 Ok(s)
168}
169
170pub fn parse_file(name: &str) -> Result<Sexp, SexpError> {
172 let s = read_file(name)?;
173 parse_str(&s[..])
174}