impl parenthesis syntax for input array initializer

This commit is contained in:
collin 2020-09-02 15:47:05 -07:00
parent b1a886640e
commit 91350a2ffe
7 changed files with 53 additions and 37 deletions

View File

@ -17,7 +17,7 @@
use crate::{
ast::Rule,
errors::SyntaxError as InputSyntaxError,
expressions::{ArrayInitializerExpression, ArrayInlineExpression, Expression},
expressions::{ArrayInlineExpression, Expression},
sections::Header,
tables::Table,
types::{DataType, Type},
@ -71,14 +71,22 @@ impl InputParserError {
}
pub fn data_type_mismatch(data_type: DataType, value: Value) -> Self {
let message = format!("expected `{}`, found `{}`", data_type.to_string(), value.to_string());
let message = format!(
"expected data type `{}`, found `{}`",
data_type.to_string(),
value.to_string()
);
let span = value.span().to_owned();
Self::new_from_span(message, span)
}
pub fn expression_type_mismatch(type_: Type, expression: Expression) -> Self {
let message = format!("expected `{}`, found `{}`", type_.to_string(), expression.to_string());
let message = format!(
"expected expression type `{}`, found `{}`",
type_.to_string(),
expression.to_string()
);
let span = expression.span().to_owned();
Self::new_from_span(message, span)
@ -95,12 +103,11 @@ impl InputParserError {
Self::new_from_span(message, span)
}
pub fn array_init_length(number: usize, array: ArrayInitializerExpression) -> Self {
pub fn array_init_length(expected: Vec<usize>, actual: Vec<usize>, span: Span) -> Self {
let message = format!(
"expected an array with a fixed size of {} elements, found one with {} elements",
number, array.count
"expected an array with a fixed size of {:?} elements, found one with {:?} elements",
expected, actual
);
let span = array.span.to_owned();
Self::new_from_span(message, span)
}

View File

@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{ast::Rule, expressions::Expression, values::PositiveNumber};
use crate::{ast::Rule, expressions::Expression, types::ArrayDimensions};
use pest::Span;
use pest_ast::FromPest;
@ -23,7 +23,7 @@ use pest_ast::FromPest;
#[pest_ast(rule(Rule::expression_array_initializer))]
pub struct ArrayInitializerExpression<'ast> {
pub expression: Box<Expression<'ast>>,
pub count: PositiveNumber<'ast>,
pub dimensions: ArrayDimensions<'ast>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}

View File

@ -44,7 +44,7 @@ impl<'ast> fmt::Display for Expression<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Expression::ArrayInitializer(ref expression) => {
write!(f, "array [{} ; {}]", expression.expression, expression.count)
write!(f, "array [{} ; {}]", expression.expression, expression.dimensions)
}
Expression::ArrayInline(ref array) => {
let values = array

View File

@ -179,7 +179,7 @@ value_address = {address | address_typed}
/// Expressions
// Declared in expressions/array_initializer_expression.rs
expression_array_initializer = { "[" ~ expression ~ ";" ~ number_positive ~ "]" }
expression_array_initializer = { "[" ~ expression ~ ";" ~ array_dimensions ~ "]" }
// Declared in expressions/array_inline_expression.rs
expression_array_inline = { "[" ~ NEWLINE* ~ inline_array_inner ~ NEWLINE* ~ "]"}

View File

@ -53,7 +53,7 @@ impl<'ast> ArrayDimensions<'ast> {
let old_dimension = multiple.numbers.clone();
ArrayDimensions::Multiple(Multiple {
numbers: old_dimension[..old_dimension.len() - 2].to_vec(),
numbers: old_dimension[..old_dimension.len() - 1].to_vec(),
span: multiple.span.clone(),
})
}
@ -65,7 +65,16 @@ impl<'ast> std::fmt::Display for ArrayDimensions<'ast> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match *self {
ArrayDimensions::Single(ref single) => write!(f, "{}", single.number),
ArrayDimensions::Multiple(ref multiple) => write!(f, "{:?}", multiple.numbers),
ArrayDimensions::Multiple(ref multiple) => {
let string = multiple
.numbers
.iter()
.map(|x| x.value.clone())
.collect::<Vec<_>>()
.join(", ");
write!(f, "{}", string)
}
}
}
}

View File

@ -33,6 +33,6 @@ pub struct ArrayType<'ast> {
impl<'ast> std::fmt::Display for ArrayType<'ast> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "[{}; {}]", self.type_, self.dimensions)
write!(f, "[{}; ({})]", self.type_, self.dimensions)
}
}

View File

@ -139,40 +139,40 @@ impl InputValue {
}
pub(crate) fn from_array_initializer(
mut array_type: ArrayType,
array_type: ArrayType,
initializer: ArrayInitializerExpression,
) -> Result<Self, InputParserError> {
let mut array_dimensions = TypedExpression::get_input_array_dimensions(array_type.dimensions.clone());
let initializer_count = initializer.count.to_string().parse::<usize>()?;
let initializer_dimensions = TypedExpression::get_input_array_dimensions(initializer.dimensions.clone());
// Return an error if the outer array dimension does not equal the number of array elements
if let Some(outer_dimension) = array_dimensions.pop() {
array_type.dimensions = array_type.dimensions.next_dimension();
if outer_dimension != initializer_count {
return Err(InputParserError::array_init_length(outer_dimension, initializer));
}
// Return an error if the array type does not equal the array expression
if array_dimensions.ne(&initializer_dimensions) {
return Err(InputParserError::array_init_length(
array_dimensions,
initializer_dimensions,
initializer.span,
));
}
let inner_array_type = if array_dimensions.len() == 0 {
// this is a single array
match array_type.type_ {
ArrayElement::Basic(basic) => Type::Basic(basic),
ArrayElement::Tuple(tuple) => Type::Tuple(tuple),
}
} else {
// this is a multi-dimensional array
Type::Array(array_type)
let type_ = match array_type.type_ {
ArrayElement::Basic(basic) => Type::Basic(basic),
ArrayElement::Tuple(tuple) => Type::Tuple(tuple),
};
let mut values = vec![];
for _ in 0..initializer_count {
let value = InputValue::from_expression(inner_array_type.clone(), *initializer.expression.clone())?;
let value = InputValue::from_expression(type_, *initializer.expression.clone())?;
let mut elements = vec![];
values.push(value)
for (i, dimension) in initializer_dimensions.into_iter().enumerate() {
if i == 0 {
elements = vec![value.clone(); dimension];
} else {
let element = InputValue::Array(elements.clone());
elements = vec![element; dimension];
}
}
Ok(InputValue::Array(values))
Ok(InputValue::Array(elements))
}
pub(crate) fn from_tuple(tuple_type: TupleType, tuple: TupleExpression) -> Result<Self, InputParserError> {