use super::complex::dict::parse_dict;
use super::complex::grid::parse_grid;
use super::complex::list::parse_list;
use super::lexer::{Lexer, TokenValue};
use super::scanner::Scanner;
use crate::haystack::val::Value;
use std::io::{Error, Read};
pub type ParserType<'a, R> = Parser<Lexer<Scanner<'a, R>>>;
pub struct Parser<Lexer> {
pub(super) lexer: Lexer,
}
impl<'a, R: Read> Parser<Lexer<Scanner<'a, R>>> {
pub fn make(input: &'a mut R) -> Result<Self, Error> {
let mut lexer = Lexer::make(input)?;
lexer.read()?;
Ok(Parser { lexer })
}
pub fn parse_value(&mut self) -> Result<Value, Error> {
match &self.lexer.cur.value {
Some(value) => match value {
TokenValue::Id(_) => {
let grid = parse_grid(self)?;
Ok(Value::make_grid(grid))
}
TokenValue::Value(value) => Ok(value.clone()),
TokenValue::ZincChar(char) => match char {
b'[' => {
let list = parse_list(self)?;
Ok(Value::make_list(list))
}
b'{' => {
let dict = parse_dict(self)?;
Ok(Value::make_dict(dict))
}
b'<' => {
let grid = parse_grid(self)?;
Ok(Value::make_grid(grid))
}
_ => self.lexer.make_generic_err(&format!(
"Unexpected parser token '{token}'",
token = *char as char
)),
},
},
None => Ok(Value::Null),
}
}
}
#[cfg(test)]
mod test {
use super::Parser;
use crate::haystack::val::Value;
use std::io::Cursor;
#[test]
fn test_zinc_parser_ok() {
let mut input = Cursor::new("^foo");
let parser = Parser::make(&mut input);
assert!(parser.is_ok());
assert_eq!(
parser.unwrap().parse_value().ok(),
Some(Value::make_symbol("foo"))
);
}
#[test]
fn test_zinc_parser_err() {
let mut input = Cursor::new("ver:@foo");
let parser = Parser::make(&mut input);
assert!(parser.is_ok());
assert_eq!(
parser
.unwrap()
.parse_value()
.map_err(|err| err.to_string())
.err(),
Some("Expecting 'ver' to be a Str, got 'Ref(Ref { value: \"foo\", dis: None })'. Input position: 7[0], line 1".into())
);
}
}