Move 'utils::bytearray' to 'expr/bytearray'

This commit is contained in:
KtorZ 2023-07-05 14:10:47 +02:00
parent 44eb501d78
commit e15cdaf248
No known key found for this signature in database
GPG Key ID: 33173CB6F77F4277
4 changed files with 89 additions and 86 deletions

View File

@ -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<Token, ast::UntypedDefinition, Error = ParseError> {
@ -48,12 +48,10 @@ pub fn value() -> impl Parser<Token, ast::Constant, Error = ParseError> {
});
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((

View File

@ -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<Token, UntypedExpr, Error = ParseError> {
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<Token, (ast::ByteArrayFormatPreference, Vec<u8>), Error = ParseError> {
choice((array_of_bytes(), hex_string(), utf8_string()))
}
pub fn array_of_bytes(
) -> impl Parser<Token, (ast::ByteArrayFormatPreference, Vec<u8>), 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::<Vec<u8>>(), base)
})
.map(|(bytes, base)| (ast::ByteArrayFormatPreference::ArrayOfBytes(base), bytes))
}
pub fn hex_string(
) -> impl Parser<Token, (ast::ByteArrayFormatPreference, Vec<u8>), 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<Token, (ast::ByteArrayFormatPreference, Vec<u8>), Error = ParseError> {
select! {Token::ByteString {value} => value.into_bytes() }
.map(|token| (ast::ByteArrayFormatPreference::Utf8String, token))
}
#[cfg(test)]
mod tests {
use crate::assert_expr;

View File

@ -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;

View File

@ -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<Token, bool, Error = ParseError> {
just(token).ignored().or_not().map(|v| v.is_some())
}
pub fn bytearray(
) -> impl Parser<Token, (ast::ByteArrayFormatPreference, Vec<u8>), 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::<Vec<u8>>(), 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<Token, (String, Option<Vec<String>>), Error = ParseError>
{
just(Token::Type).ignore_then(