Struct NumberParser

Source
pub struct NumberParser {
    pub settings: NumberParserSettings,
}
Expand description

Provide for parsing of numbers in various forms.

To use this, make an instance and then configure it if you wish.

§Plus / Minus

(Signed) numbers can start with an optional minus or plus sign to indicate the sign. If you do not want to allow the plus sign, see NumberParserSettings::permit_plus.

§Permitted Radices

The methods Self::parse_u128, Self::parse_i128, and Self::parse_f64, can parse numbers that occur in any supported radix. You can disable parsing of numbers in hexadecimal, octal, or binary by setting the appropriate flag to false. Decimal numbers cannot be disabled.

§Radix Indicator

Different radices can be detected automatically using a leading radix indicator. This is also configurable, with the following defaults.

PrefixRadix
0bBinary
0oOctal
noneDecimal
0xHexadecimal

Radix indicators can be configured if you wish, but you must be careful to avoid excessive ambiguity. The following is an example.

use trivet::numbers::NumberParser;
use trivet::ParserCore;
use trivet::errors::ParseResult;
use trivet::parse_from_string;

let mut parser = parse_from_string("17 $ffef_1021");
let mut core = parser.borrow_core();
let mut numpar = NumberParser::new();
numpar.settings.permit_binary = false;
numpar.settings.permit_octal = false;
numpar.settings.hexadecimal_indicator = vec!['$'];

assert_eq!(numpar.parse_u128(&mut core)?, 17);
core.consume();
assert_eq!(numpar.parse_u128(&mut core)?, 0xffef1021);

§Explicit Radix

Methods that explicitly specify a radix do not look for a radix indicator, and will fail if one is encountered. They also ignore the enabled/disabled status of any radix.

use trivet::numbers::NumberParser;
use trivet::numbers::Radix;
use trivet::ParserCore;
use trivet::errors::ParseResult;
use trivet::parse_from_string;

let mut parser = parse_from_string("17 ffef_1021");
let mut core = parser.borrow_core();
let mut numpar = NumberParser::new();

assert_eq!(numpar.parse_u128_radix(&mut core, Radix::Decimal)?, 17);
let _ = core.consume_ws_only();
assert_eq!(numpar.parse_u128_radix(&mut core, Radix::Hexadecimal)?, 0xffef1021);

Fields§

§settings: NumberParserSettings

The parser settings.

Implementations§

Source§

impl NumberParser

Source

pub fn new() -> Self

Make a new number parser. All options are enabled by default, and the default radix indicators are installed. This is a very permissive form of number parsing, and can be problematic for some parsers. Check the options carefully to ensure the ones you want are installed.

Examples found in repository?
examples/numbers.rs (line 9)
7pub fn main() {
8    println!("Enter a number to see how Trivet parses it.  Enter a blank line to stop.");
9    let numpar = NumberParser::new();
10    print!("> ");
11    let _ = stdout().flush();
12    for line in stdin().lock().lines() {
13        if line.is_err() {
14            break;
15        }
16        let line = line.unwrap();
17
18        // Consume any whitespace.
19        let mut parser = parse_from_string(&line);
20        parser.consume_ws();
21        if parser.is_at_eof() {
22            break;
23        }
24
25        // Try to read a number as pieces.
26        let parts = numpar.get_parts(parser.borrow_core());
27        println!("{:?}", parts);
28        if parts.is_apparent_float() {
29            let value: f64 = parts.into();
30            println!("f64: {}", value);
31        } else {
32            let value: i128 = parts.into();
33            println!("i128: {}", value);
34        }
35
36        // Go around again.
37        print!("> ");
38        let _ = stdout().flush();
39    }
40}
Source

pub fn get_text(&self, parser: &mut ParserCore) -> (Radix, String, bool)

Get the text of the next number in the stream. This extracts the longest string that matches the following expression. Note that this may not be a valid number.

[-+]? (indicator)? [0-9a-z_]* ('.' [0-9a-z_]*)? ([eEpP] [0-9a-z_]*)?

The + can be allowed or disallowed using options, and is discarded from the returned string.

The NumberParserSettings::decimal_only_floats flag is ignored. It can be checked after returning the result.

In the above indicator is any allowed radix indicator. The returned value will be a triple consisting of the apparent radix of the number, the text of the number, and a flag indicating whether the number is a floating point value.

The exponent indicator p is required iff the number is in hexadecimal. The exponent indicator p is prohibited if hexadecimal is not allowed.

This method honors the settings, so only permitted radices and the appropriate indicators are used, and underscores may or may not be permitted.

Note that even if underscores are permitted, they are discarded during parsing.

Note that tests for leading zero, empty whole, and empty fracitonal part are not performed here. Perform those on evaluation.

Several methods may be useful with respect to the output of this method.

  • i16::from_str_radix
  • i32::from_str_radix
  • i64::from_str_radix
  • i128::from_str_radix
  • u16::from_str_radix
  • u32::from_str_radix
  • u64::from_str_radix
  • u128::from_str_radix
  • f64::from_str (must use std::str::FromStr)
use trivet::parse_from_string;
use trivet::numbers::NumberParser;
use trivet::numbers::Radix;

// Parse an integer value.
let mut parser = parse_from_string("-0x21_e4");
let mut np = NumberParser::new();
let (radix, text, fp) = np.get_text(parser.borrow_core());
assert_eq!(radix, Radix::Hexadecimal);
assert_eq!(text, "-21e4".to_string());
assert_eq!(fp, false);
let value = i16::from_str_radix(&text, radix.value());
assert_eq!(value, Ok(-0x21e4));
use trivet::parse_from_string;
use trivet::numbers::NumberParser;
use trivet::numbers::Radix;
use std::str::FromStr;

// Parse a floating point value.
let mut parser = parse_from_string("-174.0210");
let mut np = NumberParser::new();
let (radix, text, fp) = np.get_text(parser.borrow_core());
assert_eq!(radix, Radix::Decimal);
assert_eq!(text, "-174.0210".to_string());
assert_eq!(fp, true);
let value = f64::from_str(&text);
assert_eq!(value, Ok(-174.0210));
Source

pub fn get_parts(&self, parser: &mut ParserCore) -> NumberParts

Parse text from the stream to generate the parts of a number.

Examples found in repository?
examples/numbers.rs (line 26)
7pub fn main() {
8    println!("Enter a number to see how Trivet parses it.  Enter a blank line to stop.");
9    let numpar = NumberParser::new();
10    print!("> ");
11    let _ = stdout().flush();
12    for line in stdin().lock().lines() {
13        if line.is_err() {
14            break;
15        }
16        let line = line.unwrap();
17
18        // Consume any whitespace.
19        let mut parser = parse_from_string(&line);
20        parser.consume_ws();
21        if parser.is_at_eof() {
22            break;
23        }
24
25        // Try to read a number as pieces.
26        let parts = numpar.get_parts(parser.borrow_core());
27        println!("{:?}", parts);
28        if parts.is_apparent_float() {
29            let value: f64 = parts.into();
30            println!("f64: {}", value);
31        } else {
32            let value: i128 = parts.into();
33            println!("i128: {}", value);
34        }
35
36        // Go around again.
37        print!("> ");
38        let _ = stdout().flush();
39    }
40}
Source

pub fn parse_f64(&self, parser: &mut ParserCore) -> ParseResult<f64>

Parse a floating point number from the stream. The number’s radix is inferred from any radix prefixes, and only the allowed integer types are checked.

Floating point numbers can be in any supported radix, and the radix indicator is checked. It is it not present, then decimal is assumed. The structure of a floating point number is as follows.

Float  ::= '-'? ( Radix)? ( 'inf' | 'infinity' | 'nan' | Number )
Radix  ::= ( '0x' | '0o' | '0b' )
Number ::= ( Digit+ |
             Digit+ '.' Digit* |
             Digit* '.' Digit+ ) Exp?
Exp    ::= ('e'|'p') ('-'|'+') Digit+
Digit  ::= [0-9a-zA-Z]

Empty whole and fractional parts may be permitted; refer to the NumberParserSettings::permit_empty_whole and NumberParserSettings::permit_empty_fraction settings. A leading zero may be allowed or not. Refer to NumberParserSettings::permit_leading_zero. If both the whole and fractional parts are empty, this is always an error.

The exponent can be indicated with either an e or a p. If the radix is hexadecimal, then only p can be used to avoid ambiguity.

Some examples.

NumberValue
0,50.5
0b0.10.5
0b1e-10.5
0o0.40.5
0x0.80.5
0x1.41.25
0x3p4196,608
0b0.12e-20.0029296875

Caution: This code does not adhere to the IEEE-754 standard for non-decimal bases! It uses a “best estimate” approach. For base 10 Self::parse_f64_decimal is used, and is intended to be compliant.

Source

pub fn parse_f64_decimal(&self, parser: &mut ParserCore) -> ParseResult<f64>

Parse a floating point number from the stream. This method assumes the number will be in decimal and does not look for, or accept, a radix specifier. Underscores are also not accepted here.

The structure of a floating point number is as follows.

Float  ::= '-'? ( 'inf' | 'infinity' | 'nan' | Number )
Number ::= ( Digit+ |
             Digit+ '.' Digit* |
             Digit* '.' Digit+ ) Exp?
Exp    ::= [eEpP] ('-'|'+') Digit+
Digit  ::= [0-9]
Source

pub fn parse_i128(&self, parser: &mut ParserCore) -> ParseResult<i128>

Read an integer from the stream at the current location and compute and return its value. Every alphanumeric character is treated as if it is part of the number. Underscores may be permitted in the number.

Number radices are read and processed here, based on the configuration.

Errors are generated if an unexpected alphanumeric character is encountered during parsing. The first non-alphanumeric stops the parse.

Source

pub fn parse_u128(&self, parser: &mut ParserCore) -> ParseResult<u128>

Read an integer from the stream at the current location and compute and return its value. Every alphanumeric character is treated as if it is part of the number. Underscores may be permitted in the number.

Number radices are read and processed here, based on the configuration.

Errors are generated if an unexpected alphanumeric character is encountered during parsing. The first non-alphanumeric stops the parse.

Source

pub fn parse_i64(&self, parser: &mut ParserCore) -> ParseResult<i64>

Read an integer from the stream at the current location and compute and return its value. Every alphanumeric character is treated as if it is part of the number. Underscores may be permitted in the number.

Number radices are read and processed here, based on the configuration.

Errors are generated if an unexpected alphanumeric character is encountered during parsing. The first non-alphanumeric stops the parse.

Source

pub fn parse_u64(&self, parser: &mut ParserCore) -> ParseResult<u64>

Read an integer from the stream at the current location and compute and return its value. Every alphanumeric character is treated as if it is part of the number. Underscores may be permitted in the number.

Number radices are read and processed here, based on the configuration.

Errors are generated if an unexpected alphanumeric character is encountered during parsing. The first non-alphanumeric stops the parse.

Source

pub fn parse_i128_radix( &self, parser: &mut ParserCore, radix: Radix, ) -> ParseResult<i128>

Read an integer from the stream at the current location and compute and return its value. Every alphanumeric character is treated as if it is part of the number. Underscores may be permitted in the number.

The number is parsed according to the given radix. Radix specifiers are not permitted.

Errors are generated if an unexpected alphanumeric character is encountered during parsing. The first non-alphanumeric stops the parse.

Source

pub fn parse_u128_radix( &self, parser: &mut ParserCore, radix: Radix, ) -> ParseResult<u128>

Read an integer from the stream at the current location and compute and return its value. Every alphanumeric character is treated as if it is part of the number. Underscores may be permitted in the number.

The number is parsed according to the given radix. Radix specifiers are not permitted.

Errors are generated if an unexpected alphanumeric character is encountered during parsing. The first non-alphanumeric stops the parse.

Source

pub fn parse_i64_radix( &self, parser: &mut ParserCore, radix: Radix, ) -> ParseResult<i64>

Read an integer from the stream at the current location and compute and return its value. Every alphanumeric character is treated as if it is part of the number. Underscores may be permitted in the number.

The number is parsed according to the given radix. Radix specifiers are not permitted.

Errors are generated if an unexpected alphanumeric character is encountered during parsing. The first non-alphanumeric stops the parse.

Source

pub fn parse_u64_radix( &self, parser: &mut ParserCore, radix: Radix, ) -> ParseResult<u64>

Read an integer from the stream at the current location and compute and return its value. Every alphanumeric character is treated as if it is part of the number. Underscores may be permitted in the number.

The number is parsed according to the given radix. Radix specifiers are not permitted.

Errors are generated if an unexpected alphanumeric character is encountered during parsing. The first non-alphanumeric stops the parse.

Trait Implementations§

Source§

impl Clone for NumberParser

Source§

fn clone(&self) -> NumberParser

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for NumberParser

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for NumberParser

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.