use panfix::parsing::{Fixity, ParseError, Parser, Pattern, Visitor}; pub fn run_parser(parser: &Parser, input: &str) -> String { use ParseError::*; match parser.parse(input) { Err(error) => match error { LexError { lexeme, pos } => format!("LexErr {} {}:{}", lexeme, pos.line, pos.column), ExtraSeparator { separator, pos } => { format!("ExtraSep {} {}:{}", separator, pos.line, pos.column) } MissingSeparator { op_name, separator, pos, } => format!( "MissingSep {} {} {}:{}", op_name, separator, pos.line, pos.column ), }, Ok(parsed) => { let mut expr = String::new(); for (i, visitor) in parsed.groups().enumerate() { parenthesize(&mut expr, visitor, &parser); if i + 1 != parsed.groups().len() { expr.push(' '); } } expr } } } fn parenthesize(out: &mut String, visitor: Visitor, parser: &Parser) { let fixity = visitor.fixity(); let mut children = visitor.children(); if children.len() == 0 { out.push_str(visitor.text()); return; } let mut delims = visitor.op_patterns(&parser).into_iter(); out.push('('); if fixity == Fixity::Infix || fixity == Fixity::Suffix { let child = children.next().unwrap(); if child.name() != "$MissingAtom" { parenthesize(out, child, parser); out.push(' '); } } let delim = delims.next().unwrap_or(None); out.push_str(pattern_to_const(delim, visitor)); while let Some(delim) = delims.next() { let child = children.next().unwrap(); out.push(' '); parenthesize(out, child, parser); out.push(' '); out.push_str(pattern_to_const(delim, visitor)); } if fixity == Fixity::Infix || fixity == Fixity::Prefix { let child = children.next().unwrap(); if child.name() != "$MissingAtom" { out.push(' '); parenthesize(out, child, parser); } } assert!(children.next().is_none()); out.push(')'); } fn pattern_to_const<'a>(pattern: Option<&'a Pattern>, visitor: Visitor<'a>) -> &'a str { match pattern { None => "?", Some(Pattern::Constant(constant)) => &constant, Some(_) => visitor.text(), } }