Skip to content
This repository was archived by the owner on Nov 26, 2020. It is now read-only.

Commit d74d140

Browse files
committed
Start of JSON parser example
1 parent 239f97c commit d74d140

File tree

5 files changed

+278
-0
lines changed

5 files changed

+278
-0
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
book
2+
target

examples/010-json/json_parser/Cargo.lock

+4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[package]
2+
name = "json_parser"
3+
version = "1.0.0"
4+
authors = ["Matt Brubeck <mbrubeck@limpet.net>"]
5+
6+
[profile.release]
7+
debug = true
+250
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
use std::collections::HashMap;
2+
use std::str::FromStr;
3+
4+
#[derive(Clone, Debug, PartialEq)]
5+
pub enum Value {
6+
String(String),
7+
Number(f64),
8+
Object(HashMap<String, Value>),
9+
Array(Vec<Value>),
10+
Bool(bool),
11+
Null
12+
}
13+
14+
#[derive(Debug, Eq, PartialEq)]
15+
pub struct ParseError;
16+
pub type ParseResult<T> = Result<T, ParseError>;
17+
18+
impl Value {
19+
pub fn from_str(s: &str) -> ParseResult<Self> {
20+
let mut parser = Parser::new(s);
21+
let value = parser.parse_value()?;
22+
parser.skip_whitespace();
23+
if parser.done() {
24+
Ok(value)
25+
} else {
26+
Err(ParseError)
27+
}
28+
}
29+
}
30+
31+
struct Parser {
32+
input: Vec<char>,
33+
pos: usize,
34+
}
35+
36+
impl Parser {
37+
fn new(s: &str) -> Self {
38+
Parser {
39+
input: s.chars().collect(),
40+
pos: 0
41+
}
42+
}
43+
44+
fn peek(&self) -> ParseResult<char> {
45+
if self.pos < self.input.len() {
46+
Ok(self.input[self.pos])
47+
} else {
48+
Err(ParseError)
49+
}
50+
}
51+
52+
fn advance(&mut self) {
53+
self.pos += 1;
54+
}
55+
56+
fn next(&mut self) -> ParseResult<char> {
57+
let c = self.peek()?;
58+
self.advance();
59+
Ok(c)
60+
}
61+
62+
fn done(&self) -> bool {
63+
self.pos >= self.input.len()
64+
}
65+
66+
fn skip_whitespace(&mut self) {
67+
while !self.done() && self.input[self.pos].is_whitespace() {
68+
self.advance();
69+
}
70+
}
71+
72+
fn expect_char(&mut self, c: char) -> ParseResult<()> {
73+
if self.next()? == c {
74+
Ok(())
75+
} else {
76+
Err(ParseError)
77+
}
78+
}
79+
80+
fn expect_str(&mut self, s: &str) -> ParseResult<()> {
81+
for c in s.chars() {
82+
self.expect_char(c)?;
83+
}
84+
Ok(())
85+
}
86+
87+
fn parse_value(&mut self) -> ParseResult<Value> {
88+
self.skip_whitespace();
89+
match self.peek()? {
90+
'"' => self.parse_string(),
91+
'{' => self.parse_object(),
92+
'[' => self.parse_array(),
93+
't' => self.parse_true(),
94+
'f' => self.parse_false(),
95+
'n' => self.parse_null(),
96+
'-' | '0'...'9' => self.parse_number(),
97+
_ => Err(ParseError)
98+
}
99+
}
100+
101+
fn parse_string(&mut self) -> ParseResult<Value> {
102+
self.expect_char('"')?;
103+
104+
let mut s = String::new();
105+
loop {
106+
match self.next()? {
107+
'"' => break,
108+
'\\' => match self.next()? {
109+
'\\' => s.push('\\'),
110+
'"' => s.push('"'),
111+
'/' => s.push('/'),
112+
'n' => s.push('\n'),
113+
'r' => s.push('\r'),
114+
't' => s.push('\t'),
115+
'b' => s.push('\u{10}'),
116+
'f' => s.push('\u{14}'),
117+
'u' => unimplemented!(),
118+
_ => return Err(ParseError)
119+
},
120+
x => s.push(x)
121+
}
122+
}
123+
Ok(Value::String(s))
124+
}
125+
126+
fn parse_number(&mut self) -> ParseResult<Value> {
127+
let mut s = String::new();
128+
129+
// Optional negative sign.
130+
if self.peek()? == '-' {
131+
s.push('-');
132+
self.advance();
133+
}
134+
135+
// A single '0' or one or more digits.
136+
match self.peek()? {
137+
'0' => {
138+
s.push('0');
139+
self.advance();
140+
}
141+
_ => s += &self.parse_digits()?
142+
}
143+
144+
// Optional fractional part.
145+
if self.peek() == Ok('.') {
146+
s.push('.');
147+
self.advance();
148+
s += &self.parse_digits()?;
149+
}
150+
151+
// Optional exponent.
152+
match self.peek() {
153+
Ok('e') | Ok('E') => {
154+
s.push('e');
155+
self.advance();
156+
// Optional sign.
157+
match self.peek()? {
158+
sign @ '+' | sign @ '-' => {
159+
s.push(sign);
160+
self.advance();
161+
}
162+
_ => {}
163+
}
164+
s += &self.parse_digits()?;
165+
}
166+
_ => {}
167+
}
168+
169+
// Use Rust's f64 parser to parse the number
170+
let num = f64::from_str(&s).or(Err(ParseError))?;
171+
Ok(Value::Number(num))
172+
}
173+
174+
/// Consume one or more digits '0'...'9' and return them as a string.
175+
fn parse_digits(&mut self) -> ParseResult<String> {
176+
let mut s = String::new();
177+
match self.peek()? {
178+
'0'...'9' => while let Ok(digit @ '0'...'9') = self.peek() {
179+
s.push(digit);
180+
self.advance();
181+
},
182+
_ => return Err(ParseError)
183+
}
184+
Ok(s)
185+
}
186+
187+
fn parse_object(&mut self) -> ParseResult<Value> {
188+
self.expect_char('{')?;
189+
190+
let mut map = HashMap::new();
191+
loop {
192+
self.skip_whitespace();
193+
let key = match self.parse_string()? {
194+
Value::String(s) => s,
195+
_ => unreachable!()
196+
};
197+
198+
self.skip_whitespace();
199+
self.expect_char(':')?;
200+
201+
self.skip_whitespace();
202+
let value = self.parse_value()?;
203+
204+
map.insert(key, value);
205+
206+
self.skip_whitespace();
207+
match self.next()? {
208+
'}' => break,
209+
',' => continue,
210+
_ => return Err(ParseError)
211+
}
212+
}
213+
Ok(Value::Object(map))
214+
}
215+
216+
fn parse_array(&mut self) -> ParseResult<Value> {
217+
self.expect_char('[')?;
218+
219+
let mut values = vec![];
220+
loop {
221+
self.skip_whitespace();
222+
match self.peek()? {
223+
']' => { self.advance(); break }
224+
_ => values.push(self.parse_value()?)
225+
}
226+
self.skip_whitespace();
227+
match self.next()? {
228+
']' => break,
229+
',' => continue,
230+
_ => return Err(ParseError)
231+
}
232+
}
233+
Ok(Value::Array(values))
234+
}
235+
236+
fn parse_true(&mut self) -> ParseResult<Value> {
237+
self.expect_str("true")?;
238+
Ok(Value::Bool(true))
239+
}
240+
241+
fn parse_false(&mut self) -> ParseResult<Value> {
242+
self.expect_str("false")?;
243+
Ok(Value::Bool(false))
244+
}
245+
246+
fn parse_null(&mut self) -> ParseResult<Value> {
247+
self.expect_str("null")?;
248+
Ok(Value::Null)
249+
}
250+
}
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
extern crate json_parser;
2+
use json_parser::Value;
3+
use std::env::args_os;
4+
use std::fs::File;
5+
use std::io::BufReader;
6+
use std::io::prelude::*;
7+
8+
fn main() {
9+
let path = args_os().skip(1).next().expect("usage: json_parser <filename>");
10+
let mut file = BufReader::new(File::open(path).expect("could not open file"));
11+
12+
let mut s = String::new();
13+
file.read_to_string(&mut s).unwrap();
14+
15+
Value::from_str(&s).unwrap();
16+
}

0 commit comments

Comments
 (0)