use crate::ast::{Token, Value};
use crate::error::{Error, Result, Span};
use crate::lazy::{LazyParser, LazyValue};
use std::sync::Arc;
#[derive(Debug, Clone)]
pub struct LazyArray {
pub(super) elements: Vec<LazyValue>,
#[allow(dead_code)]
pub(super) input: Arc<str>,
#[allow(dead_code)]
pub(super) options: crate::parser::ParserOptions,
}
impl LazyArray {
pub fn new(input: Arc<str>, options: crate::parser::ParserOptions) -> Self {
LazyArray {
elements: Vec::new(),
input,
options,
}
}
pub fn push(&mut self, value: LazyValue) {
self.elements.push(value);
}
pub fn get(&self, index: usize) -> Option<Result<Value>> {
self.elements.get(index).map(|lazy_val| lazy_val.evaluate())
}
pub fn get_lazy(&self, index: usize) -> Option<&LazyValue> {
self.elements.get(index)
}
pub fn len(&self) -> usize {
self.elements.len()
}
pub fn is_empty(&self) -> bool {
self.elements.is_empty()
}
pub fn iter(&self) -> impl Iterator<Item = &LazyValue> {
self.elements.iter()
}
pub fn evaluate_all(&self) -> Result<Value> {
let mut resolved_arr = Vec::new();
for lazy_val in &self.elements {
resolved_arr.push(lazy_val.evaluate()?);
}
Ok(Value::Array(resolved_arr))
}
}
impl<'a> LazyParser<'a> {
pub(super) fn parse_array(&mut self, _start_span: Span) -> Result<Value> {
self.parse_array_immediate()
}
pub(super) fn parse_array_immediate(&mut self) -> Result<Value> {
let mut array = Vec::new();
let mut first = true;
loop {
loop {
let (next_token, _) = self.peek_token()?;
if next_token == Token::Newline {
self.next_token()?;
} else {
break;
}
}
let (next_token, _) = self.peek_token()?;
if next_token == Token::RightBracket {
self.next_token()?;
break;
}
if !first {
let (token, span) = self.next_token()?;
match token {
Token::Comma => {}
Token::Newline if self.options.newline_as_comma => {}
Token::RightBracket if self.options.allow_trailing_commas => break,
_ => {
return Err(Error::Expected {
expected: "comma or ]".to_string(),
found: format!("{token:?}"),
position: span.start,
});
}
}
}
first = false;
let (value_token, value_span) = self.next_token()?;
let value = self.parse_value(value_token, value_span)?;
array.push(value);
}
Ok(Value::Array(array))
}
}