chronlang-parser 0.1.7

A parser for Chronlang, a computer language for crafting constructed languages.
Documentation
use chumsky::{prelude::*, text::{Character, ident} };
use crate::ast::{
  Feature,
  Category,
};

pub fn inline_whitespace() -> impl Parser<char, (), Error = Simple<char>> {
  filter(|c: &char| c.is_inline_whitespace())
    .repeated()
    .ignored()
}

pub fn word_char() -> impl Parser<char, char, Error = Simple<char>> {
  filter(|c: &char| !"/.,[]{}()>+-_#".contains(*c) && !c.is_whitespace())
}

pub fn word_chars() -> impl Parser<char, String, Error = Simple<char>> {
  word_char()
    .repeated()
    .at_least(1)
    .map(|cs| cs.iter().collect())
}

pub fn class() -> impl Parser<char, char, Error = Simple<char>> {
  filter(|c: &char| c.is_ascii_uppercase())
}

pub fn description() -> impl Parser<char, String, Error = Simple<char>> {
  filter(|c: &char| !"\r\n{}".contains(*c))
    .repeated()
    .at_least(1)
    .map(|cs| cs.iter().collect())
}

pub fn syllable() -> impl Parser<char, String, Error = Simple<char>> {
  word_char()
    .repeated()
    .at_least(1)
    .map(|cs| cs.iter().collect())
}

pub fn feature() -> impl Parser<char, Feature, Error = Simple<char>> {
  let sign = filter(|c: &char| "+-".contains(*c));
  let ident = ident();
  
  sign
    .then(ident)
    .padded()
    .map(|(s, i)| match s {
      '+' => Feature::Positive(i),
      _ => Feature::Negative(i),
    })
}

pub fn category() -> impl Parser<char, Category, Error = Simple<char>> {
  class()
    .map_with_span(|class, span| (span, class))
    .padded()
    .or_not()
    .then(
      feature()
        .map_with_span(|feat, span| (span, feat))
        .repeated()
        .at_least(1)
    )
    .delimited_by(just("["), just("]"))
    .map(|(base_class, features)| Category { base_class, features })
}

pub fn integer() -> impl Parser<char, i64, Error = Simple<char>> {
  filter(|c: &char| c.is_numeric())
    .repeated()
    .at_least(1)
    .try_map(|cs, span| cs
      .iter()
      .collect::<String>()
      .parse::<i64>()
      .map_err(|e| Simple::custom(span, format!("{}", e))))
}