Move 'utils::bytearray' to 'expr/bytearray'
This commit is contained in:
parent
44eb501d78
commit
e15cdaf248
|
@ -2,7 +2,7 @@ use chumsky::prelude::*;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast,
|
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> {
|
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 =
|
let constant_bytearray_parser =
|
||||||
utils::bytearray().map_with_span(|(preferred_format, bytes), span| {
|
bytearray().map_with_span(|(preferred_format, bytes), span| ast::Constant::ByteArray {
|
||||||
ast::Constant::ByteArray {
|
location: span,
|
||||||
location: span,
|
bytes,
|
||||||
bytes,
|
preferred_format,
|
||||||
preferred_format,
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
choice((
|
choice((
|
||||||
|
|
|
@ -1,18 +1,98 @@
|
||||||
use chumsky::prelude::*;
|
use chumsky::prelude::*;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
ast,
|
||||||
expr::UntypedExpr,
|
expr::UntypedExpr,
|
||||||
parser::{error::ParseError, token::Token, utils},
|
parser::{
|
||||||
|
error::{self, ParseError},
|
||||||
|
token::{Base, Token},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn parser() -> impl Parser<Token, UntypedExpr, Error = ParseError> {
|
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,
|
location: span,
|
||||||
bytes,
|
bytes,
|
||||||
preferred_format,
|
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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::assert_expr;
|
use crate::assert_expr;
|
||||||
|
|
|
@ -5,7 +5,7 @@ mod anonymous_binop;
|
||||||
pub mod anonymous_function;
|
pub mod anonymous_function;
|
||||||
pub mod assignment;
|
pub mod assignment;
|
||||||
mod block;
|
mod block;
|
||||||
mod bytearray;
|
pub(crate) mod bytearray;
|
||||||
mod if_else;
|
mod if_else;
|
||||||
mod int;
|
mod int;
|
||||||
mod list;
|
mod list;
|
||||||
|
|
|
@ -1,86 +1,11 @@
|
||||||
use chumsky::prelude::*;
|
use chumsky::prelude::*;
|
||||||
|
|
||||||
use crate::ast;
|
use super::{error::ParseError, token::Token};
|
||||||
|
|
||||||
use super::{
|
|
||||||
error::{self, ParseError},
|
|
||||||
token::{Base, Token},
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn optional_flag(token: Token) -> impl Parser<Token, bool, Error = ParseError> {
|
pub fn optional_flag(token: Token) -> impl Parser<Token, bool, Error = ParseError> {
|
||||||
just(token).ignored().or_not().map(|v| v.is_some())
|
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>
|
pub fn type_name_with_args() -> impl Parser<Token, (String, Option<Vec<String>>), Error = ParseError>
|
||||||
{
|
{
|
||||||
just(Token::Type).ignore_then(
|
just(Token::Type).ignore_then(
|
||||||
|
|
Loading…
Reference in New Issue