From 030699beb5f9ed334409d9d2fed7e5cf64f3f5f2 Mon Sep 17 00:00:00 2001 From: collin Date: Mon, 13 Apr 2020 11:17:29 -0700 Subject: [PATCH] pest array, postfix, array access --- simple.program | 3 +- src/aleo_program/types_from.rs | 11 ++ src/ast.rs | 273 +++++++++++++++++++++++++++++---- src/language.pest | 58 +++++-- 4 files changed, 305 insertions(+), 40 deletions(-) diff --git a/simple.program b/simple.program index 8f3857339d..3e56c3789f 100644 --- a/simple.program +++ b/simple.program @@ -1 +1,2 @@ -return if a then 1 else 0 fi \ No newline at end of file +field[1] f = [1; 3] +return 1 \ No newline at end of file diff --git a/src/aleo_program/types_from.rs b/src/aleo_program/types_from.rs index ede1f0e8c1..0856409207 100644 --- a/src/aleo_program/types_from.rs +++ b/src/aleo_program/types_from.rs @@ -285,6 +285,7 @@ impl<'ast> From> for types::Expression { ast::Expression::Not(expression) => types::Expression::from(expression), ast::Expression::Binary(expression) => types::Expression::from(expression), ast::Expression::Ternary(expression) => types::Expression::from(expression), + _ => unimplemented!(), } } } @@ -298,6 +299,15 @@ impl<'ast> From> for types::Statement { } } +impl<'ast> From> for types::Statement { + fn from(statement: ast::DefinitionStatement<'ast>) -> Self { + types::Statement::Definition( + types::Variable::from(statement.variable), + types::Expression::from(statement.expression), + ) + } +} + impl<'ast> From> for types::Statement { fn from(statement: ast::ReturnStatement<'ast>) -> Self { types::Statement::Return( @@ -314,6 +324,7 @@ impl<'ast> From> for types::Statement { fn from(statement: ast::Statement<'ast>) -> Self { match statement { ast::Statement::Assign(statement) => types::Statement::from(statement), + ast::Statement::Definition(statement) => types::Statement::from(statement), ast::Statement::Return(statement) => types::Statement::from(statement), } } diff --git a/src/ast.rs b/src/ast.rs index 8041576618..894949c5d2 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -13,6 +13,7 @@ use pest::{ }; use pest_ast::FromPest; use std::fmt; +use std::fmt::Formatter; #[derive(Parser)] #[grammar = "language.pest"] @@ -54,6 +55,41 @@ fn parse_term(pair: Pair) -> Box { let clone = pair.clone(); let next = clone.into_inner().next().unwrap(); match next.as_rule() { + Rule::expression => Expression::from_pest(&mut pair.into_inner()).unwrap(), // Parenthesis case + Rule::expression_array_inline => { + println!("array inline"); + Expression::ArrayInline( + ArrayInlineExpression::from_pest(&mut pair.into_inner()).unwrap() + ) + }, + Rule::expression_array_initializer => { + println!("array initializer"); + Expression::ArrayInitializer( + ArrayInitializerExpression::from_pest(&mut pair.into_inner()).unwrap() + ) + }, + Rule::expression_conditional => { + println!("conditional expression"); + Expression::Ternary( + TernaryExpression::from_pest(&mut pair.into_inner()).unwrap(), + ) + }, + Rule::expression_not => { + let span = next.as_span(); + let mut inner = next.into_inner(); + let operation = match inner.next().unwrap().as_rule() { + Rule::operation_pre_not => Not::from_pest(&mut pair.into_inner().next().unwrap().into_inner()).unwrap(), + rule => unreachable!("`expression_not` should yield `operation_pre_not`, found {:#?}", rule) + }; + let expression = parse_term(inner.next().unwrap()); + Expression::Not(NotExpression { operation, expression, span }) + }, + Rule::expression_postfix => { + println!("postfix expression"); + Expression::Postfix( + PostfixExpression::from_pest(&mut pair.into_inner()).unwrap(), + ) + } Rule::expression_primitive => { let next = next.into_inner().next().unwrap(); match next.as_rule() { @@ -65,25 +101,7 @@ fn parse_term(pair: Pair) -> Box { ), rule => unreachable!("`expression_primitive` should contain one of [`value`, `variable`], found {:#?}", rule) } - } - Rule::expression_not => { - let span = next.as_span(); - let mut inner = next.into_inner(); - let operation = match inner.next().unwrap().as_rule() { - Rule::operation_pre_not => Not::from_pest(&mut pair.into_inner().next().unwrap().into_inner()).unwrap(), - rule => unreachable!("`expression_not` should yield `operation_pre_not`, found {:#?}", rule) - }; - let expression = parse_term(inner.next().unwrap()); - Expression::Not(NotExpression { operation, expression, span }) }, - Rule::expression_conditional => { - println!("conditional expression"); - Expression::Ternary( - TernaryExpression::from_pest(&mut pair.into_inner()).unwrap(), - ) - } - Rule::expression => Expression::from_pest(&mut pair.into_inner()).unwrap(), // Parenthesis case - // Rule::expression_increment => { // let span = next.as_span(); // let mut inner = next.into_inner(); @@ -151,6 +169,61 @@ pub struct File<'ast> { pub span: Span<'ast>, } +// Types + +#[derive(Debug, FromPest, PartialEq, Clone)] +#[pest_ast(rule(Rule::ty_bool))] +pub struct BooleanType<'ast> { + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +#[derive(Debug, FromPest, PartialEq, Clone)] +#[pest_ast(rule(Rule::ty_field))] +pub struct FieldType<'ast> { + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +// #[derive(Debug, FromPest, PartialEq, Clone)] +// #[pest_ast(rule(Rule::ty_struct))] +// pub struct StructType<'ast> { +// pub id: IdentifierExpression<'ast>, +// #[pest_ast(outer())] +// pub span: Span<'ast>, +// } +// +#[derive(Debug, FromPest, PartialEq, Clone)] +#[pest_ast(rule(Rule::ty_basic))] +pub enum BasicType<'ast> { + Field(FieldType<'ast>), + Boolean(BooleanType<'ast>), +} + +// #[derive(Debug, FromPest, PartialEq, Clone)] +// #[pest_ast(rule(Rule::ty_basic_or_struct))] +// pub enum BasicOrStructType<'ast> { +// Struct(StructType<'ast>), +// Basic(BasicType<'ast>), +// } + +#[derive(Debug, FromPest, PartialEq, Clone)] +#[pest_ast(rule(Rule::ty_array))] +pub struct ArrayType<'ast> { + pub ty: BasicType<'ast>, + pub dimensions: Vec>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +#[derive(Debug, FromPest, PartialEq, Clone)] +#[pest_ast(rule(Rule::ty))] +pub enum Type<'ast> { + // Basic(BasicType<'ast>), + Array(ArrayType<'ast>), + // Struct(StructType<'ast>), +} + // Visibility #[derive(Clone, Debug, FromPest, PartialEq)] @@ -284,6 +357,122 @@ impl<'ast> fmt::Display for Variable<'ast> { } } +// Access + +#[derive(Debug, FromPest, PartialEq, Clone)] +#[pest_ast(rule(Rule::from_expression))] +pub struct FromExpression<'ast>(pub Expression<'ast>); + +#[derive(Debug, FromPest, PartialEq, Clone)] +#[pest_ast(rule(Rule::to_expression))] +pub struct ToExpression<'ast>(pub Expression<'ast>); + +#[derive(Debug, FromPest, PartialEq, Clone)] +#[pest_ast(rule(Rule::range))] +pub struct Range<'ast> { + pub from: Option>, + pub to: Option>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +#[derive(Debug, FromPest, PartialEq, Clone)] +#[pest_ast(rule(Rule::range_or_expression))] +pub enum RangeOrExpression<'ast> { + Range(Range<'ast>), + Expression(Expression<'ast>), +} + +// #[derive(Debug, FromPest, PartialEq, Clone)] +// #[pest_ast(rule(Rule::call_access))] +// pub struct CallAccess<'ast> { +// pub expressions: Vec>, +// #[pest_ast(outer())] +// pub span: Span<'ast>, +// } + +#[derive(Debug, FromPest, PartialEq, Clone)] +#[pest_ast(rule(Rule::access_array))] +pub struct ArrayAccess<'ast> { + pub expression: RangeOrExpression<'ast>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +// #[derive(Debug, FromPest, PartialEq, Clone)] +// #[pest_ast(rule(Rule::member_access))] +// pub struct MemberAccess<'ast> { +// pub id: IdentifierExpression<'ast>, +// #[pest_ast(outer())] +// pub span: Span<'ast>, +// } + +#[derive(Debug, FromPest, PartialEq, Clone)] +#[pest_ast(rule(Rule::access))] +pub enum Access<'ast> { + // Call(CallAccess<'ast>), + Select(ArrayAccess<'ast>), + // Member(MemberAccess<'ast>), +} + +#[derive(Debug, FromPest, PartialEq, Clone)] +#[pest_ast(rule(Rule::expression_postfix))] +pub struct PostfixExpression<'ast> { + pub variable: Variable<'ast>, + pub accesses: Vec>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +#[derive(Debug, FromPest, PartialEq, Clone)] +#[pest_ast(rule(Rule::spread))] +pub struct Spread<'ast> { + pub expression: Expression<'ast>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +impl<'ast> fmt::Display for Spread<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "...{}", self.expression) + } +} + +#[derive(Debug, FromPest, PartialEq, Clone)] +#[pest_ast(rule(Rule::spread_or_expression))] +pub enum SpreadOrExpression<'ast> { + Spread(Spread<'ast>), + Expression(Expression<'ast>), +} + +impl<'ast> fmt::Display for SpreadOrExpression<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + SpreadOrExpression::Spread(ref spread) => write!(f, "{}", spread), + SpreadOrExpression::Expression(ref expression) => write!(f, "{}", expression), + } + } +} + +// Arrays + +#[derive(Debug, FromPest, PartialEq, Clone)] +#[pest_ast(rule(Rule::expression_array_inline))] +pub struct ArrayInlineExpression<'ast> { + pub expressions: Vec>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +#[derive(Debug, FromPest, PartialEq, Clone)] +#[pest_ast(rule(Rule::expression_array_initializer))] +pub struct ArrayInitializerExpression<'ast> { + pub expression: Box>, + pub value: Value<'ast>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + // Expressions #[derive(Clone, Debug, FromPest, PartialEq)] @@ -331,12 +520,6 @@ pub struct TernaryExpression<'ast> { pub span: Span<'ast>, } -// #[derive(Clong, Debug, PartialEq)] -// pub struct IdentifierExpression<'ast> { -// pub value: String, -// pub span: Span<'ast>, -// } - #[derive(Clone, Debug, PartialEq)] pub enum Expression<'ast> { Value(Value<'ast>), @@ -344,8 +527,10 @@ pub enum Expression<'ast> { Not(NotExpression<'ast>), Binary(BinaryExpression<'ast>), Ternary(TernaryExpression<'ast>), - // Increment(IncrementExpression<'ast>), - // Decrement(DecrementExpression<'ast>), + ArrayInline(ArrayInlineExpression<'ast>), + ArrayInitializer(ArrayInitializerExpression<'ast>), + Postfix(PostfixExpression<'ast>), // Increment(IncrementExpression<'ast>), + // Decrement(DecrementExpression<'ast>) } impl<'ast> Expression<'ast> { @@ -384,6 +569,9 @@ impl<'ast> Expression<'ast> { Expression::Not(expression) => &expression.span, Expression::Binary(expression) => &expression.span, Expression::Ternary(expression) => &expression.span, + Expression::ArrayInline(expression) => &expression.span, + Expression::ArrayInitializer(expression) => &expression.span, + Expression::Postfix(expression) => &expression.span, // Expression::Increment(expression) => &expression.span, // Expression::Decrement(expression) => &expression.span, } @@ -404,6 +592,21 @@ impl<'ast> fmt::Display for Expression<'ast> { "if {} then {} else {} fi", expression.first, expression.second, expression.third ), + Expression::ArrayInline(ref expression) => { + for (i, spread_or_expression) in expression.expressions.iter().enumerate() { + write!(f, "{}", spread_or_expression)?; + if i < expression.expressions.len() - 1 { + write!(f, ", ")?; + } + } + write!(f, "") + } + Expression::ArrayInitializer(ref expression) => { + write!(f, "{} = {}", expression.value, expression.expression) + } + Expression::Postfix(ref expression) => { + write!(f, "Postfix display not impl {}", expression.variable) + } } } } @@ -463,17 +666,35 @@ impl<'ast> fmt::Display for ReturnStatement<'ast> { } } +#[derive(Debug, FromPest, PartialEq, Clone)] +#[pest_ast(rule(Rule::statement_definition))] +pub struct DefinitionStatement<'ast> { + pub ty: Type<'ast>, + pub variable: Variable<'ast>, + pub expression: Expression<'ast>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + #[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::statement))] pub enum Statement<'ast> { Assign(AssignStatement<'ast>), + Definition(DefinitionStatement<'ast>), Return(ReturnStatement<'ast>), } +impl<'ast> fmt::Display for DefinitionStatement<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.expression) + } +} + impl<'ast> fmt::Display for Statement<'ast> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { Statement::Assign(ref statement) => write!(f, "{}", statement), + Statement::Definition(ref statement) => write!(f, "{}", statement), Statement::Return(ref statement) => write!(f, "{}", statement), } } diff --git a/src/language.pest b/src/language.pest index 0a6a5cbb8e..837e0d43f2 100644 --- a/src/language.pest +++ b/src/language.pest @@ -47,13 +47,25 @@ operation_binary = _ { // operation_mul_assign = { "*=" } // operation_div_assign = { "/=" } +/// Types + +ty_field = {"field"} +ty_bool = {"bool"} +ty_basic = { ty_field | ty_bool } +ty_basic_or_struct = {ty_basic | ty_struct } +ty_array = {ty_basic ~ ("[" ~ expression ~ "]")+ } +// ty = {ty_array | ty_basic | ty_struct} +ty = {ty_array} +type_list = _{(ty ~ ("," ~ ty)*)?} + +/// Structs + +ty_struct = { variable } + /// Values value_boolean = { "true" | "false" } value_field = @{ "-"? ~ ("0" | ASCII_NONZERO_DIGIT ~ ASCII_DIGIT*) } - -// TODO: Boolean array, field array - value = { value_boolean | value_field } /// Variables @@ -67,18 +79,26 @@ protected_name = { visibility | value_boolean | "return" } variable = @{ ((!protected_name ~ ASCII_ALPHA) | (protected_name ~ (ASCII_ALPHANUMERIC | "_"))) ~ (ASCII_ALPHANUMERIC | "_")* } -/// Expressions +/// Access -// Consider structs, conditionals, postfix, primary, inline array, array initializer, and unary -expression_primitive = { value | variable } -expression_not = { operation_pre_not ~ expression_term } -expression_term = { ("(" ~ expression ~ ")") | expression_conditional | expression_primitive | expression_not} +from_expression = { expression } +to_expression = { expression } +range = { from_expression? ~ ".." ~ to_expression } +range_or_expression = { range | expression } +access_array = { "[" ~ range_or_expression ~ "]" } +access = { access_array } +expression_postfix = { variable ~ access } -expression = { expression_term ~ (operation_binary ~ expression_term)* } -// expression_increment = { expression ~ operation_post_increment } -// expression_decrement = { expression ~ operation_post_decrement } +spread = { "..." ~ expression } +spread_or_expression = { spread | expression } -// Conditionals +/// Arrays + +inline_array_inner = _{(spread_or_expression ~ ("," ~ NEWLINE* ~ spread_or_expression)*)?} +expression_array_inline = { "[" ~ NEWLINE* ~ inline_array_inner ~ NEWLINE* ~ "]"} +expression_array_initializer = { "[" ~ expression ~ ";" ~ value ~ "]" } + +/// Conditionals expression_conditional = { "if" ~ expression ~ "then" ~ expression ~ "else" ~ expression ~ "fi"} // conditional_if = { "if" } @@ -88,6 +108,17 @@ expression_conditional = { "if" ~ expression ~ "then" ~ expression ~ "else" ~ ex // // conditional = { conditional_if | conditional_else | conditional_for } +/// Expressions + +// Consider structs, conditionals, postfix, primary, inline array, array initializer, and unary +expression_primitive = { value | variable } +expression_not = { operation_pre_not ~ expression_term } +expression_term = { ("(" ~ expression ~ ")") | expression_conditional | expression_postfix | expression_primitive | expression_not | expression_array_inline | expression_array_initializer} + +expression = { expression_term ~ (operation_binary ~ expression_term)* } +// expression_increment = { expression ~ operation_post_increment } +// expression_decrement = { expression ~ operation_post_decrement } + expression_tuple = _{ (expression ~ ("," ~ expression)*)? } @@ -95,9 +126,10 @@ expression_tuple = _{ (expression ~ ("," ~ expression)*)? } /// Statements statement_assign = { variable ~ "=" ~ expression } +statement_definition = { ty ~ variable ~ "=" ~ expression } statement_return = { "return" ~ expression_tuple } -statement = { (statement_return | (statement_assign) ~ NEWLINE) ~ NEWLINE* } +statement = { (statement_return | (statement_assign | statement_definition) ~ NEWLINE) ~ NEWLINE* } /// Utilities