Hi, I'm writing a JSON (not compliant) parser with a top-down parsing method to practice my Rust programming.
Here is the (full repo)[GitHub - Celthi/parsing-rs: Experiment writing JSON parser with Rust]. There are several tests to test the parser and the lexer. It seems it is working, but the code written is not as idiomatic as I think it is. For example, for parsing a object, the code is,
fn parse_object<'a, 'b>(
lexemes: &'a [Lexeme<'b>],
) -> Result<(Value, &'a [Lexeme<'b>]), &'static str> {
if lexemes.len() < 2 || lexemes[0]._type != b'{' {
return Err("Not a object.");
}
// empty object
if lexemes[1]._type == b'}' {
return Ok((Value::Object(HashMap::new()), &lexemes[2..]));
}
let mut m = HashMap::new();
let mut lexemes = &lexemes[1..];
loop {
if let (Value::String(s), lexeme) = parse_string(lexemes)? {
if lexeme[0]._type != b':' {
return Err("colon expected.");
}
lexemes = &lexeme[1..];
let (value, lexeme) = parse_value(lexemes)?;
m.insert(s, value);
if lexeme[0]._type != b',' {
lexemes = lexeme;
break;
}
lexemes = &lexeme[1..];
}
}
if lexemes.len() < 1 || lexemes[0]._type != b'}' {
return Err("right bracket expected.");
}
return Ok((Value::Object(m), &lexemes[1..]));
}
I was thinking to improve this code snippet by extracting the following code into a function
if let (Value::String(s), lexeme) = parse_string(lexemes)? {
if lexeme[0]._type != b':' {
return Err("colon expected.");
}
lexemes = &lexeme[1..];
let (value, lexeme) = parse_value(lexemes)?;
m.insert(s, value);
if lexeme[0]._type != b',' {
lexemes = lexeme;
break;
}
lexemes = &lexeme[1..];
But it seems I need to return three things: the lexemes have not parsed, the key and value of the object have parsed, and error if there is any.
Could you give some ideas (general or specific) and I will try them to improve the code to practice my skills? Appreciate any comments! Or recommend that I read other well-written JSON parsers with the same techniques (top-down with tokenizing).
I have read the serde_json library, but I find it is not using a top-down parser, so I cannot do an apple and apple comparison.