use elyze::acceptor::Acceptor;
use elyze::bytes::primitives::number::Number;
use elyze::bytes::primitives::string::DataString;
use elyze::bytes::token::Token;
use elyze::errors::ParseError::UnexpectedToken;
use elyze::errors::ParseResult;
use elyze::recognizer::recognize;
use elyze::scanner::Scanner;
use elyze::visitor::Visitor;
#[derive(Debug)]
struct RgbColor(u8, u8, u8);
#[derive(Debug)]
struct HexColor(u8, u8, u8);
struct TupleColor(u8, u8, u8);
enum ColorInternal {
Rgb(RgbColor),
Hex(HexColor),
Tuple(TupleColor),
}
impl From<ColorInternal> for Color {
fn from(value: ColorInternal) -> Self {
match value {
ColorInternal::Rgb(rgb) => Color(rgb.0, rgb.1, rgb.2),
ColorInternal::Hex(hex) => Color(hex.0, hex.1, hex.2),
ColorInternal::Tuple(tuple) => Color(tuple.0, tuple.1, tuple.2),
}
}
}
impl<'a> Visitor<'a, u8> for TupleColor {
fn accept(scanner: &mut Scanner<u8>) -> ParseResult<Self> {
recognize(Token::OpenParen, scanner)?;
let red = Number::accept(scanner)?.0;
recognize(Token::Comma, scanner)?;
recognize(Token::Whitespace, scanner)?;
let green = Number::accept(scanner)?.0;
recognize(Token::Comma, scanner)?;
recognize(Token::Whitespace, scanner)?;
let blue = Number::accept(scanner)?.0;
recognize(Token::CloseParen, scanner)?;
Ok(TupleColor(red, green, blue))
}
}
impl<'a> Visitor<'a, u8> for RgbColor {
fn accept(scanner: &mut Scanner<u8>) -> ParseResult<Self> {
let prefix = DataString::<&str>::accept(scanner)?.0;
if prefix != "rgb" {
return Err(UnexpectedToken);
}
recognize(Token::OpenParen, scanner)?;
let red = Number::accept(scanner)?.0;
recognize(Token::Comma, scanner)?;
recognize(Token::Whitespace, scanner)?;
let green = Number::accept(scanner)?.0;
recognize(Token::Comma, scanner)?;
recognize(Token::Whitespace, scanner)?;
let blue = Number::accept(scanner)?.0;
recognize(Token::CloseParen, scanner)?;
Ok(RgbColor(red, green, blue))
}
}
impl<'a> Visitor<'a, u8> for HexColor {
fn accept(scanner: &mut Scanner<u8>) -> ParseResult<Self> {
recognize(Token::Sharp, scanner)?;
let content = DataString::<&str>::accept(scanner)?.0;
let (red, green, blue) = (
u8::from_str_radix(&content[0..2], 16)?,
u8::from_str_radix(&content[2..4], 16)?,
u8::from_str_radix(&content[4..6], 16)?,
);
Ok(HexColor(red, green, blue))
}
}
#[derive(Debug)]
#[allow(dead_code)]
pub struct Color(u8, u8, u8);
impl<'a> Visitor<'a, u8> for Color {
fn accept(scanner: &mut Scanner<u8>) -> ParseResult<Self> {
let color = Acceptor::new(scanner)
.try_or(ColorInternal::Hex)?
.try_or(ColorInternal::Rgb)?
.try_or(ColorInternal::Tuple)?
.finish()
.ok_or(UnexpectedToken)?;
Ok(color.into())
}
}
fn main() {
let data = b"rgb(255, 0, 0)";
let mut scanner = Scanner::new(data);
let result = Color::accept(&mut scanner);
println!("{:?}", result);
let data = b"#ff0000";
let mut scanner = Scanner::new(data);
let result = Color::accept(&mut scanner);
println!("{:?}", result);
let data = b"(255, 0, 0)";
let mut scanner = Scanner::new(data);
let result = Color::accept(&mut scanner);
println!("{:?}", result);
}