rust/hedgewars-server/src/server/haskell.rs
changeset 15577 7d4f552e317f
parent 15576 3be9c98ae190
child 15578 0b6094660557
equal deleted inserted replaced
15576:3be9c98ae190 15577:7d4f552e317f
       
     1 use crate::server::haskell::HaskellValue::Boolean;
     1 use nom::{
     2 use nom::{
     2     branch::alt,
     3     branch::alt,
     3     bytes::complete::{escaped_transform, is_not, tag, take_while, take_while1},
     4     bytes::complete::{escaped_transform, is_not, tag, take_while, take_while1},
     4     character::{is_alphanumeric, is_digit, is_space},
     5     character::{is_alphanumeric, is_digit, is_space},
     5     combinator::{map, map_res},
     6     combinator::{map, map_res},
    10 use std::{
    11 use std::{
    11     collections::HashMap,
    12     collections::HashMap,
    12     fmt::{Display, Error, Formatter},
    13     fmt::{Display, Error, Formatter},
    13 };
    14 };
    14 
    15 
    15 type HaskellResult<'a, T> = IResult<&'a [u8], T, ()>;
    16 type HaskellResult<'a, T> = IResult<&'a [u8], T>;
    16 
    17 
    17 #[derive(Debug, PartialEq)]
    18 #[derive(Debug, PartialEq)]
    18 pub enum HaskellValue {
    19 pub enum HaskellValue {
       
    20     Boolean(bool),
    19     Number(u8),
    21     Number(u8),
    20     String(String),
    22     String(String),
    21     Tuple(Vec<HaskellValue>),
    23     Tuple(Vec<HaskellValue>),
    22     List(Vec<HaskellValue>),
    24     List(Vec<HaskellValue>),
    23     AnonStruct {
    25     AnonStruct {
   124 }
   126 }
   125 
   127 
   126 impl Display for HaskellValue {
   128 impl Display for HaskellValue {
   127     fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
   129     fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
   128         match self {
   130         match self {
       
   131             HaskellValue::Boolean(value) => write!(f, "{}", if *value { "True" } else { "False" }),
   129             HaskellValue::Number(value) => write!(f, "{}", value),
   132             HaskellValue::Number(value) => write!(f, "{}", value),
   130             HaskellValue::String(value) => write_text(f, value),
   133             HaskellValue::String(value) => write_text(f, value),
   131             HaskellValue::Tuple(items) => write_sequence(f, b"()", items.iter()),
   134             HaskellValue::Tuple(items) => write_sequence(f, b"()", items.iter()),
   132             HaskellValue::List(items) => write_sequence(f, b"[]", items.iter()),
   135             HaskellValue::List(items) => write_sequence(f, b"[]", items.iter()),
   133             HaskellValue::AnonStruct { name, fields } => {
   136             HaskellValue::AnonStruct { name, fields } => {
   167             delimited(take_while(is_space), tag(prefix), take_while(is_space)),
   170             delimited(take_while(is_space), tag(prefix), take_while(is_space)),
   168             |i| parser(i),
   171             |i| parser(i),
   169             delimited(take_while(is_space), tag(suffix), take_while(is_space)),
   172             delimited(take_while(is_space), tag(suffix), take_while(is_space)),
   170         )(input)
   173         )(input)
   171     }
   174     }
       
   175 }
       
   176 
       
   177 fn boolean(input: &[u8]) -> HaskellResult<HaskellValue> {
       
   178     map(
       
   179         alt((map(tag("True"), |_| true), map(tag("False"), |_| false))),
       
   180         HaskellValue::Boolean,
       
   181     )(input)
   172 }
   182 }
   173 
   183 
   174 fn number_raw(input: &[u8]) -> HaskellResult<u8> {
   184 fn number_raw(input: &[u8]) -> HaskellResult<u8> {
   175     use std::str::FromStr;
   185     use std::str::FromStr;
   176     map_res(take_while(is_digit), |s| {
   186     map_res(take_while(is_digit), |s| {
   266         |bytes| String::from_utf8(bytes).map_err(|_| ()),
   276         |bytes| String::from_utf8(bytes).map_err(|_| ()),
   267     )(input)
   277     )(input)
   268 }
   278 }
   269 
   279 
   270 fn string(input: &[u8]) -> HaskellResult<HaskellValue> {
   280 fn string(input: &[u8]) -> HaskellResult<HaskellValue> {
   271     map(surrounded("\"", "\"", string_content), HaskellValue::String)(input)
   281     map(
       
   282         delimited(tag("\""), string_content, tag("\"")),
       
   283         HaskellValue::String,
       
   284     )(input)
   272 }
   285 }
   273 
   286 
   274 fn tuple(input: &[u8]) -> HaskellResult<HaskellValue> {
   287 fn tuple(input: &[u8]) -> HaskellResult<HaskellValue> {
   275     map(
   288     map(
   276         surrounded("(", ")", separated_list(comma, value)),
   289         surrounded("(", ")", separated_list(comma, value)),
   312             },
   325             },
   313         ),
   326         ),
   314         map(
   327         map(
   315             pair(
   328             pair(
   316                 identifier,
   329                 identifier,
   317                 preceded(take_while1(is_space), separated_list(comma, value)),
   330                 preceded(
       
   331                     take_while(is_space),
       
   332                     separated_list(take_while1(is_space), value),
       
   333                 ),
   318             ),
   334             ),
   319             |(name, mut fields)| HaskellValue::AnonStruct {
   335             |(name, mut fields)| HaskellValue::AnonStruct {
   320                 name: name.clone(),
   336                 name: name.clone(),
   321                 fields,
   337                 fields,
   322             },
   338             },
   323         ),
   339         ),
   324     ))(input)
   340     ))(input)
   325 }
   341 }
   326 
   342 
   327 fn value(input: &[u8]) -> HaskellResult<HaskellValue> {
   343 fn value(input: &[u8]) -> HaskellResult<HaskellValue> {
   328     alt((number, string, tuple, list, structure))(input)
   344     alt((boolean, number, string, tuple, list, structure))(input)
   329 }
   345 }
   330 
   346 
   331 #[inline]
   347 #[inline]
   332 pub fn parse(input: &[u8]) -> HaskellResult<HaskellValue> {
   348 pub fn parse(input: &[u8]) -> HaskellResult<HaskellValue> {
   333     delimited(take_while(is_space), value, take_while(is_space))(input)
   349     delimited(take_while(is_space), value, take_while(is_space))(input)
   339     #[test]
   355     #[test]
   340     fn terminals() {
   356     fn terminals() {
   341         use HaskellValue::*;
   357         use HaskellValue::*;
   342 
   358 
   343         matches!(number(b"127"), Ok((_, Number(127))));
   359         matches!(number(b"127"), Ok((_, Number(127))));
   344         matches!(number(b"adas"), Err(nom::Err::Error(())));
   360         matches!(number(b"adas"), Err(nom::Err::Error(_)));
   345 
   361 
   346         assert_eq!(
   362         assert_eq!(
   347             string(b"\"Hail \\240\\159\\166\\148!\""),
   363             string(b"\"Hail \\240\\159\\166\\148!\""),
   348             Ok((&b""[..], String("Hail \u{1f994}!".to_string())))
   364             Ok((&b""[..], String("Hail \u{1f994}!".to_string())))
   349         );
   365         );
   384             Ok((&b""[..], value))
   400             Ok((&b""[..], value))
   385         );
   401         );
   386 
   402 
   387         let value = AnonStruct {
   403         let value = AnonStruct {
   388             name: "Hog".to_string(),
   404             name: "Hog".to_string(),
   389             fields: vec![Number(100), String("\u{1f994}".to_string())],
   405             fields: vec![Boolean(true), Number(100), String("\u{1f994}".to_string())],
   390         };
   406         };
   391 
   407 
   392         assert_eq!(
   408         assert_eq!(
   393             structure(b"Hog 100, \"\\240\\159\\166\\148\""),
   409             structure(b"Hog True 100 \"\\240\\159\\166\\148\""),
   394             Ok((&b""[..], value))
   410             Ok((&b""[..], value))
   395         );
   411         );
   396     }
   412     }
   397 }
   413 }