json_parser/
parser.rs

1use crate::error::Error;
2use crate::result::Result;
3use crate::tokenizer::Tokenizer;
4use crate::tokenizer::{PeekableIter, Token};
5use std::collections::HashMap;
6use std::str::FromStr;
7
8#[derive(Debug, PartialEq)]
9pub enum Json {
10  Null,
11  Bool(bool),
12  Number(f64),
13  String(String),
14  Array(Vec<Box<Json>>),
15  Object(HashMap<String, Box<Json>>),
16}
17
18impl FromStr for Json {
19  type Err = Error;
20  fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
21    let mut token_stream: PeekableIter<Token> =
22      s.parse::<Tokenizer>()?.tokenize()?.into_iter().peekable();
23    parse_item(&mut token_stream)
24  }
25}
26
27fn skip_token(token_stream: &mut PeekableIter<Token>, token: Token) -> Result<()> {
28  match token_stream.next() {
29    Some(ref tkn) if *tkn == token => Ok(()),
30    _ => Err(Error::Parse("token expected".into())),
31  }
32}
33
34fn parse_array(token_stream: &mut PeekableIter<Token>) -> Result<Json> {
35  skip_token(token_stream, Token::SquareOpen)?;
36  let mut v = vec![];
37  loop {
38    match token_stream.peek() {
39      Some(Token::SquareClose) => break,
40      Some(_) => {
41        v.push(Box::new(parse_item(token_stream)?));
42        if let Some(Token::SquareClose) = token_stream.peek() {
43          continue;
44        }
45        skip_token(token_stream, Token::Coma)?;
46      }
47      _ => return Err(Error::Parse("unterminated array".into())),
48    }
49  }
50  skip_token(token_stream, Token::SquareClose)?;
51  Ok(Json::Array(v))
52}
53
54fn parse_object(token_stream: &mut PeekableIter<Token>) -> Result<Json> {
55  skip_token(token_stream, Token::CurlyOpen)?;
56  let mut obj: HashMap<String, Box<Json>> = HashMap::default();
57  loop {
58    match token_stream.peek() {
59      Some(Token::CurlyClose) => break,
60      Some(_) => {
61        if let Json::String(key) = parse_string(token_stream)? {
62          skip_token(token_stream, Token::Colon)?;
63          let val = parse_item(token_stream)?;
64          obj.insert(key, Box::new(val));
65          if let Some(Token::CurlyClose) = token_stream.peek() {
66            continue;
67          }
68          skip_token(token_stream, Token::Coma)?;
69        } else {
70          return Err(Error::Parse("object key expected".into()));
71        }
72      }
73      _ => return Err(Error::Parse("unterminated object".into())),
74    }
75  }
76  skip_token(token_stream, Token::CurlyClose)?;
77  return Ok(Json::Object(obj));
78}
79
80pub fn parse_item(token_stream: &mut PeekableIter<Token>) -> Result<Json> {
81  match token_stream.peek() {
82    Some(Token::NullValue) => parse_null(token_stream),
83    Some(Token::BoolValue(_)) => parse_bool(token_stream),
84    Some(Token::NumberValue(_)) => parse_number(token_stream),
85    Some(Token::StringValue(_)) => parse_string(token_stream),
86    Some(Token::SquareOpen) => parse_array(token_stream),
87    Some(Token::CurlyOpen) => parse_object(token_stream),
88    _ => Err(Error::Parse("unexpected token".into())),
89  }
90}
91
92pub fn parse_null(token_stream: &mut PeekableIter<Token>) -> Result<Json> {
93  match token_stream.next() {
94    Some(Token::NullValue) => Ok(Json::Null),
95    _ => Err(Error::Parse("null expected".into())),
96  }
97}
98
99pub fn parse_bool(token_stream: &mut PeekableIter<Token>) -> Result<Json> {
100  match token_stream.next() {
101    Some(Token::BoolValue(b)) => Ok(Json::Bool(b)),
102    _ => Err(Error::Parse("bool expected".into())),
103  }
104}
105
106pub fn parse_number(token_stream: &mut PeekableIter<Token>) -> Result<Json> {
107  match token_stream.next() {
108    Some(Token::NumberValue(n)) => Ok(Json::Number(n)),
109    _ => Err(Error::Parse("number expected".into())),
110  }
111}
112
113pub fn parse_string(token_stream: &mut PeekableIter<Token>) -> Result<Json> {
114  match token_stream.next() {
115    Some(Token::StringValue(s)) => Ok(Json::String(s)),
116    _ => Err(Error::Parse("string expected".into())),
117  }
118}