use std::collections::HashMap; use winnow::combinator::alt; use winnow::combinator::cut_err; use winnow::combinator::preceded; use winnow::combinator::separated; use winnow::combinator::separated_pair; use winnow::combinator::delimited; use winnow::combinator::terminated; use winnow::stream::AsChar; use winnow::token::take_while; use winnow::{PResult, Parser}; struct Object { elements: HashMap, } enum Value { Str(String), Array(Vec), Object(HashMap), } fn value<'s>(input: &mut &'s str) -> PResult { alt((string.map(Value::Str), array.map(Value::Object), object.map(Value:Object), )).parse_next(input) } fn array<'s>(input: &mut &'s str) -> PResult> { preceded( ('[', ws), cut_err(terminated( separated(0.., value, ws), (ws, ']'), )), ) .context("array") .parse_next(input) } fn object<'s>(input: &mut &'s str) -> PResult> { preceded( ('{', ws), cut_err(terminated( separated(0.., value, ws), (ws, '}'), )), ) .context("object") .parse_next(input) } fn string<'s>(input: &mut &'s str) -> PResult<&'s str> { delimited(ws, alphanum_1, ws).parse_next(input) } fn alphanum_1<'s>(input: &mut &'s str) -> PResult<&'s str> { // one_of(('0'..='9', 'a'..='f', 'A'..='F')).parse_next(input) take_while(1.., (AsChar::is_alphanum, is_underscore)).parse_next(input) } fn is_underscore(c: char) -> bool { c == '_' } fn ws<'s>(input: &mut &'s str) -> PResult<&'s str> { take_while(0.., &[' ', '\t', '\r', '\n', ',', ':', '=']).parse_next(input) } fn key_value<'s>(input: &mut &'s str) -> PResult<(String, Value)> { separated_pair(string, cut_err(ws), value).parse_next(input) } fn main() { let mut ex1 = " whirly_widgets 10 twirly_widgets 15 girly_widgets 4 burly_widgets 1 "; let output = string.parse_next(&mut ex1).unwrap(); println!("parsed: {}", output); }