Move parsing of literals under new 'literal' parser module group
Also moved the logic for 'int' and 'string' there though it is trivial. Yet, for bytearray, it tidies things nicely by removing them from the 'utils' module.
This commit is contained in:
		
							parent
							
								
									e15cdaf248
								
							
						
					
					
						commit
						66296df9c3
					
				|  | @ -4,6 +4,7 @@ pub mod error; | |||
| pub mod expr; | ||||
| pub mod extra; | ||||
| pub mod lexer; | ||||
| pub mod literal; | ||||
| pub mod pattern; | ||||
| pub mod token; | ||||
| mod utils; | ||||
|  |  | |||
|  | @ -2,7 +2,9 @@ use chumsky::prelude::*; | |||
| 
 | ||||
| use crate::{ | ||||
|     ast, | ||||
|     parser::{annotation, error::ParseError, expr::bytearray::bytearray, token::Token, utils}, | ||||
|     parser::{ | ||||
|         annotation, error::ParseError, literal::bytearray::parser as bytearray, token::Token, utils, | ||||
|     }, | ||||
| }; | ||||
| 
 | ||||
| pub fn parser() -> impl Parser<Token, ast::UntypedDefinition, Error = ParseError> { | ||||
|  | @ -48,7 +50,7 @@ pub fn value() -> impl Parser<Token, ast::Constant, Error = ParseError> { | |||
|         }); | ||||
| 
 | ||||
|     let constant_bytearray_parser = | ||||
|         bytearray().map_with_span(|(preferred_format, bytes), span| ast::Constant::ByteArray { | ||||
|         bytearray(|bytes, preferred_format, span| ast::Constant::ByteArray { | ||||
|             location: span, | ||||
|             bytes, | ||||
|             preferred_format, | ||||
|  |  | |||
|  | @ -1,98 +1,17 @@ | |||
| use chumsky::prelude::*; | ||||
| 
 | ||||
| use crate::{ | ||||
|     ast, | ||||
|     expr::UntypedExpr, | ||||
|     parser::{ | ||||
|         error::{self, ParseError}, | ||||
|         token::{Base, Token}, | ||||
|     }, | ||||
| use crate::parser::{ | ||||
|     error::ParseError, expr::UntypedExpr, literal::bytearray::parser as bytearray, token::Token, | ||||
| }; | ||||
| 
 | ||||
| pub fn parser() -> impl Parser<Token, UntypedExpr, Error = ParseError> { | ||||
|     bytearray().map_with_span(|(preferred_format, bytes), span| UntypedExpr::ByteArray { | ||||
|         location: span, | ||||
|     bytearray(|bytes, preferred_format, location| UntypedExpr::ByteArray { | ||||
|         location, | ||||
|         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; | ||||
|  |  | |||
|  | @ -2,16 +2,14 @@ use chumsky::prelude::*; | |||
| 
 | ||||
| use crate::{ | ||||
|     expr::UntypedExpr, | ||||
|     parser::{error::ParseError, token::Token}, | ||||
|     parser::{error::ParseError, literal::int::parser as int, token::Token}, | ||||
| }; | ||||
| 
 | ||||
| pub fn parser() -> impl Parser<Token, UntypedExpr, Error = ParseError> { | ||||
|     select! { Token::Int {value, base} => (value, base)}.map_with_span(|(value, base), span| { | ||||
|         UntypedExpr::Int { | ||||
|     int().map_with_span(|(value, base), span| UntypedExpr::Int { | ||||
|         location: span, | ||||
|         value, | ||||
|         base, | ||||
|         } | ||||
|     }) | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -3,11 +3,11 @@ use chumsky::prelude::*; | |||
| use crate::{ | ||||
|     ast, | ||||
|     expr::UntypedExpr, | ||||
|     parser::{error::ParseError, token::Token}, | ||||
|     parser::{error::ParseError, literal::string::parser as string, token::Token}, | ||||
| }; | ||||
| 
 | ||||
| pub fn parser() -> impl Parser<Token, UntypedExpr, Error = ParseError> { | ||||
|     select! {Token::String {value} => value}.map_with_span(|value, span| UntypedExpr::String { | ||||
|     string().map_with_span(|value, span| UntypedExpr::String { | ||||
|         location: span, | ||||
|         value, | ||||
|     }) | ||||
|  |  | |||
|  | @ -0,0 +1,87 @@ | |||
| use chumsky::prelude::*; | ||||
| 
 | ||||
| use crate::{ | ||||
|     ast, | ||||
|     parser::{ | ||||
|         error::{self, ParseError}, | ||||
|         token::{Base, Token}, | ||||
|     }, | ||||
| }; | ||||
| 
 | ||||
| pub fn parser<A>( | ||||
|     into: impl Fn(Vec<u8>, ast::ByteArrayFormatPreference, ast::Span) -> A, | ||||
| ) -> impl Parser<Token, A, Error = ParseError> { | ||||
|     choice((array_of_bytes(), hex_string(), utf8_string())) | ||||
|         .map_with_span(move |(preferred_format, bytes), span| into(bytes, preferred_format, span)) | ||||
| } | ||||
| 
 | ||||
| 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)) | ||||
| } | ||||
|  | @ -0,0 +1,10 @@ | |||
| use chumsky::prelude::*; | ||||
| 
 | ||||
| use crate::parser::{ | ||||
|     error::ParseError, | ||||
|     token::{Base, Token}, | ||||
| }; | ||||
| 
 | ||||
| pub fn parser() -> impl Parser<Token, (String, Base), Error = ParseError> { | ||||
|     select! { Token::Int {value, base} => (value, base)} | ||||
| } | ||||
|  | @ -0,0 +1,3 @@ | |||
| pub(crate) mod bytearray; | ||||
| pub(crate) mod int; | ||||
| pub(crate) mod string; | ||||
|  | @ -0,0 +1,7 @@ | |||
| use chumsky::prelude::*; | ||||
| 
 | ||||
| use crate::parser::{error::ParseError, token::Token}; | ||||
| 
 | ||||
| pub fn parser() -> impl Parser<Token, String, Error = ParseError> { | ||||
|     select! {Token::String {value} => value} | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	 KtorZ
						KtorZ