Mini Parser
Level: intro (score: 1)
🚀 These intro exercises are prep for our
Rust Intro Cohort Program.
🎯 Mini Parser Challenge: Parse a Primitive
You’ll parse a single JSON‑style primitive from a string:
true,false,null- integer (base‑10, optional leading
+or-, at least one digit)
Ignore leading/trailing ASCII whitespace. Input must contain exactly one primitive (no extra trailing chars after trimming).
✅ Your task
Define:
#[derive(Debug, PartialEq, Eq)]
pub enum JsonValue {
Bool(bool),
Null,
Number(i64),
}
#[derive(Debug, PartialEq, Eq)]
pub enum ParseError {
Empty,
Invalid,
Overflow,
}
Implement:
pub fn parse_primitive(input: &str) -> Result<JsonValue, ParseError>
Rules:
- Trim ASCII whitespace first; if empty →
Err(ParseError::Empty) - Accept exactly
"true","false","null" - Else parse an integer with optional
+/-prefix; on parse failure →Invalid - If the integer doesn’t fit in
i64→Overflow - Reject any extra non‑whitespace after the token (e.g.
"123abc") →Invalid
💡 Hints
- Use
trim()to strip ws; then decide which branch to take. - For integers, manually scan the sign and digits; don’t accept
_or empty digits. - Use
i128for accumulation and check bounds againsti64::MIN..=i64::MAXbefore casting.
Example tests:
use JsonValue::*; use ParseError::*;
assert_eq!(parse_primitive("true"), Ok(Bool(true)));
assert_eq!(parse_primitive(" false "), Ok(Bool(false)));
assert_eq!(parse_primitive("null"), Ok(Null));
assert_eq!(parse_primitive("42"), Ok(Number(42)));
assert_eq!(parse_primitive("-7"), Ok(Number(-7)));
assert_eq!(parse_primitive("+9"), Ok(Number(9)));
assert_eq!(parse_primitive(""), Err(Empty));
assert_eq!(parse_primitive(" "), Err(Empty));
assert_eq!(parse_primitive("12x"), Err(Invalid));
#[derive(Debug, PartialEq, Eq)]
pub enum JsonValue {
Bool(bool),
Null,
Number(i64),
}
#[derive(Debug, PartialEq, Eq)]
pub enum ParseError {
Empty,
Invalid,
Overflow,
}
pub fn parse_primitive(input: &str) -> Result<JsonValue, ParseError> {
// TODO:
// - trim
// - match true/false/null
// - else parse signed integer (at least one digit)
// - check i64 bounds
// - return precise errors
unimplemented!()
}
#[cfg(test)]
mod tests {
use super::*;
use JsonValue::*;
use ParseError::*;
#[test]
fn test_bools_null() {
assert_eq!(parse_primitive("true"), Ok(Bool(true)));
assert_eq!(parse_primitive(" false "), Ok(Bool(false)));
assert_eq!(parse_primitive("null"), Ok(Null));
}
#[test]
fn test_integers() {
assert_eq!(parse_primitive("42"), Ok(Number(42)));
assert_eq!(parse_primitive("-7"), Ok(Number(-7)));
assert_eq!(parse_primitive("+9"), Ok(Number(9)));
}
#[test]
fn test_errors() {
assert_eq!(parse_primitive(""), Err(Empty));
assert_eq!(parse_primitive(" "), Err(Empty));
assert_eq!(parse_primitive("12x"), Err(Invalid));
assert_eq!(parse_primitive("+"), Err(Invalid));
assert_eq!(parse_primitive("-"), Err(Invalid));
}
}