From e15cdaf2484d497f3dfca89d6ace42e007c20063 Mon Sep 17 00:00:00 2001 From: KtorZ Date: Wed, 5 Jul 2023 14:10:47 +0200 Subject: [PATCH] Move 'utils::bytearray' to 'expr/bytearray' --- .../src/parser/definition/constant.rs | 12 ++- .../aiken-lang/src/parser/expr/bytearray.rs | 84 ++++++++++++++++++- crates/aiken-lang/src/parser/expr/mod.rs | 2 +- crates/aiken-lang/src/parser/utils.rs | 77 +---------------- 4 files changed, 89 insertions(+), 86 deletions(-) diff --git a/crates/aiken-lang/src/parser/definition/constant.rs b/crates/aiken-lang/src/parser/definition/constant.rs index 093c9d69..8963707b 100644 --- a/crates/aiken-lang/src/parser/definition/constant.rs +++ b/crates/aiken-lang/src/parser/definition/constant.rs @@ -2,7 +2,7 @@ use chumsky::prelude::*; use crate::{ ast, - parser::{annotation, error::ParseError, token::Token, utils}, + parser::{annotation, error::ParseError, expr::bytearray::bytearray, token::Token, utils}, }; pub fn parser() -> impl Parser { @@ -48,12 +48,10 @@ pub fn value() -> impl Parser { }); let constant_bytearray_parser = - utils::bytearray().map_with_span(|(preferred_format, bytes), span| { - ast::Constant::ByteArray { - location: span, - bytes, - preferred_format, - } + bytearray().map_with_span(|(preferred_format, bytes), span| ast::Constant::ByteArray { + location: span, + bytes, + preferred_format, }); choice(( diff --git a/crates/aiken-lang/src/parser/expr/bytearray.rs b/crates/aiken-lang/src/parser/expr/bytearray.rs index 756f6312..0b46c4db 100644 --- a/crates/aiken-lang/src/parser/expr/bytearray.rs +++ b/crates/aiken-lang/src/parser/expr/bytearray.rs @@ -1,18 +1,98 @@ use chumsky::prelude::*; use crate::{ + ast, expr::UntypedExpr, - parser::{error::ParseError, token::Token, utils}, + parser::{ + error::{self, ParseError}, + token::{Base, Token}, + }, }; pub fn parser() -> impl Parser { - utils::bytearray().map_with_span(|(preferred_format, bytes), span| UntypedExpr::ByteArray { + bytearray().map_with_span(|(preferred_format, bytes), span| UntypedExpr::ByteArray { location: span, bytes, preferred_format, }) } +pub fn bytearray( +) -> impl Parser), Error = ParseError> { + choice((array_of_bytes(), hex_string(), utf8_string())) +} + +pub fn array_of_bytes( +) -> impl Parser), Error = ParseError> { + just(Token::Hash) + .ignore_then( + select! {Token::Int {value, base, ..} => (value, base)} + .validate(|(value, base), span, emit| { + let byte: u8 = match value.parse() { + Ok(b) => b, + Err(_) => { + emit(ParseError::expected_input_found( + span, + None, + Some(error::Pattern::Byte), + )); + 0 + } + }; + (byte, base) + }) + .separated_by(just(Token::Comma)) + .allow_trailing() + .delimited_by(just(Token::LeftSquare), just(Token::RightSquare)), + ) + .validate(|bytes, span, emit| { + let base = bytes.iter().fold(Ok(None), |acc, (_, base)| match acc { + Ok(None) => Ok(Some(base)), + Ok(Some(previous_base)) if previous_base == base => Ok(Some(base)), + _ => Err(()), + }); + + let base = match base { + Err(()) => { + emit(ParseError::hybrid_notation_in_bytearray(span)); + Base::Decimal { + numeric_underscore: false, + } + } + Ok(None) => Base::Decimal { + numeric_underscore: false, + }, + Ok(Some(base)) => *base, + }; + + (bytes.into_iter().map(|(b, _)| b).collect::>(), base) + }) + .map(|(bytes, base)| (ast::ByteArrayFormatPreference::ArrayOfBytes(base), bytes)) +} + +pub fn hex_string( +) -> impl Parser), Error = ParseError> { + just(Token::Hash) + .ignore_then( + select! {Token::ByteString {value} => value}.validate(|value, span, emit| { + match hex::decode(value) { + Ok(bytes) => bytes, + Err(_) => { + emit(ParseError::malformed_base16_string_literal(span)); + vec![] + } + } + }), + ) + .map(|token| (ast::ByteArrayFormatPreference::HexadecimalString, token)) +} + +pub fn utf8_string( +) -> impl Parser), Error = ParseError> { + select! {Token::ByteString {value} => value.into_bytes() } + .map(|token| (ast::ByteArrayFormatPreference::Utf8String, token)) +} + #[cfg(test)] mod tests { use crate::assert_expr; diff --git a/crates/aiken-lang/src/parser/expr/mod.rs b/crates/aiken-lang/src/parser/expr/mod.rs index db134436..05455021 100644 --- a/crates/aiken-lang/src/parser/expr/mod.rs +++ b/crates/aiken-lang/src/parser/expr/mod.rs @@ -5,7 +5,7 @@ mod anonymous_binop; pub mod anonymous_function; pub mod assignment; mod block; -mod bytearray; +pub(crate) mod bytearray; mod if_else; mod int; mod list; diff --git a/crates/aiken-lang/src/parser/utils.rs b/crates/aiken-lang/src/parser/utils.rs index 60099769..f45a639e 100644 --- a/crates/aiken-lang/src/parser/utils.rs +++ b/crates/aiken-lang/src/parser/utils.rs @@ -1,86 +1,11 @@ use chumsky::prelude::*; -use crate::ast; - -use super::{ - error::{self, ParseError}, - token::{Base, Token}, -}; +use super::{error::ParseError, token::Token}; pub fn optional_flag(token: Token) -> impl Parser { just(token).ignored().or_not().map(|v| v.is_some()) } -pub fn bytearray( -) -> impl Parser), Error = ParseError> { - let bytearray_list_parser = just(Token::Hash) - .ignore_then( - select! {Token::Int {value, base, ..} => (value, base)} - .validate(|(value, base), span, emit| { - let byte: u8 = match value.parse() { - Ok(b) => b, - Err(_) => { - emit(ParseError::expected_input_found( - span, - None, - Some(error::Pattern::Byte), - )); - 0 - } - }; - (byte, base) - }) - .separated_by(just(Token::Comma)) - .allow_trailing() - .delimited_by(just(Token::LeftSquare), just(Token::RightSquare)), - ) - .validate(|bytes, span, emit| { - let base = bytes.iter().fold(Ok(None), |acc, (_, base)| match acc { - Ok(None) => Ok(Some(base)), - Ok(Some(previous_base)) if previous_base == base => Ok(Some(base)), - _ => Err(()), - }); - - let base = match base { - Err(()) => { - emit(ParseError::hybrid_notation_in_bytearray(span)); - Base::Decimal { - numeric_underscore: false, - } - } - Ok(None) => Base::Decimal { - numeric_underscore: false, - }, - Ok(Some(base)) => *base, - }; - - (bytes.into_iter().map(|(b, _)| b).collect::>(), base) - }) - .map(|(bytes, base)| (ast::ByteArrayFormatPreference::ArrayOfBytes(base), bytes)); - - let bytearray_hexstring_parser = - just(Token::Hash) - .ignore_then(select! {Token::ByteString {value} => value}.validate( - |value, span, emit| match hex::decode(value) { - Ok(bytes) => bytes, - Err(_) => { - emit(ParseError::malformed_base16_string_literal(span)); - vec![] - } - }, - )) - .map(|token| (ast::ByteArrayFormatPreference::HexadecimalString, token)); - - let bytearray_utf8_parser = select! {Token::ByteString {value} => value.into_bytes() } - .map(|token| (ast::ByteArrayFormatPreference::Utf8String, token)); - - choice(( - bytearray_list_parser, - bytearray_hexstring_parser, - bytearray_utf8_parser, - )) -} - pub fn type_name_with_args() -> impl Parser>), Error = ParseError> { just(Token::Type).ignore_then(