duckling 0.4.0

A Rust port of Facebook's Duckling library for parsing natural language into structured data
Documentation
use crate::pattern::regex;
use crate::types::{Rule, TokenData};

use super::NumeralData;

fn khmer_digit_to_ascii(c: char) -> char {
    match c {
        '០' => '0',
        '១' => '1',
        '២' => '2',
        '៣' => '3',
        '៤' => '4',
        '៥' => '5',
        '៦' => '6',
        '៧' => '7',
        '៨' => '8',
        '៩' => '9',
        _ => c,
    }
}

fn lex_value(s: &str) -> Option<f64> {
    match s {
        "សូន្យ" => Some(0.0),
        "មួយ" => Some(1.0),
        "ពីរ" => Some(2.0),
        "បី" => Some(3.0),
        "បួន" => Some(4.0),
        "ប្រាំ" => Some(5.0),
        "ប្រាំមួយ" => Some(6.0),
        "ប្រាំពីរ" => Some(7.0),
        "ប្រាំបី" => Some(8.0),
        "ប្រាំបួន" => Some(9.0),
        "ដប់" => Some(10.0),
        "ដប់មួយ" => Some(11.0),
        "ម្ភៃពីរ" => Some(22.0),
        "សាមបី" => Some(33.0),
        "កៅប្រាំបួន" => Some(99.0),
        "បីរយម្ភៃ" => Some(320.0),
        "ប្រាំមួយពាន់ចិតប្រាំបី" => Some(6078.0),
        "ប្រាំលានប្រាំមួយសែនប្រាំបីម៉ឺនប្រាំបួនពាន់បួនរយសែបី" => {
            Some(5689443.0)
        }
        "ប្រាំបីរយលាន" => Some(800000000.0),
        _ => None,
    }
}

pub fn rules() -> Vec<Rule> {
    vec![
        Rule {
            name: "khmer forms".to_string(),
            pattern: vec![regex("([០១២៣៤៥៦៧៨៩]{1,18})")],
            production: Box::new(|nodes| {
                let s = match &nodes[0].token_data {
                    TokenData::RegexMatch(m) => m.group(1)?,
                    _ => return None,
                };
                let ascii: String = s.chars().map(khmer_digit_to_ascii).collect();
                let v: f64 = ascii.parse().ok()?;
                Some(TokenData::Numeral(NumeralData::new(v)))
            }),
        },
        Rule {
            name: "lexical numerals".to_string(),
            pattern: vec![regex("(សូន្យ|មួយ|ពីរ|បី|បួន|ប្រាំមួយ|ប្រាំពីរ|ប្រាំបី|ប្រាំបួន|ប្រាំ|ដប់មួយ|ដប់|ម្ភៃពីរ|សាមបី|កៅប្រាំបួន|បីរយម្ភៃ|ប្រាំមួយពាន់ចិតប្រាំបី|ប្រាំលានប្រាំមួយសែនប្រាំបីម៉ឺនប្រាំបួនពាន់បួនរយសែបី|ប្រាំបីរយលាន)")],
            production: Box::new(|nodes| {
                let s = match &nodes[0].token_data {
                    TokenData::RegexMatch(m) => m.group(1)?,
                    _ => return None,
                };
                Some(TokenData::Numeral(NumeralData::new(lex_value(s)?)))
            }),
        },
    ]
}