From 227e844154d9a592b80a88d7b8731d3d2f2fb3e2 Mon Sep 17 00:00:00 2001 From: Titus Wormer Date: Wed, 22 Jun 2022 15:20:33 +0200 Subject: Add `attempt_opt` to tokenizer --- src/construct/partial_space_or_tab.rs | 59 ++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 25 deletions(-) (limited to 'src/construct/partial_space_or_tab.rs') diff --git a/src/construct/partial_space_or_tab.rs b/src/construct/partial_space_or_tab.rs index cbb2cf3..024a4b2 100644 --- a/src/construct/partial_space_or_tab.rs +++ b/src/construct/partial_space_or_tab.rs @@ -8,24 +8,31 @@ use crate::tokenizer::{Code, State, StateFn, StateFnResult, TokenType, Tokenizer /// Options to parse whitespace. #[derive(Debug)] -struct Info { - /// Current size. - size: usize, +pub struct Options { /// Minimum allowed characters (inclusive). - min: usize, + pub min: usize, /// Maximum allowed characters (inclusive). - max: usize, + pub max: usize, /// Token type to use for whitespace events. - kind: TokenType, + pub kind: TokenType, +} + +/// Options to parse whitespace. +#[derive(Debug)] +struct Info { + /// Current size. + size: usize, + /// Configuration. + options: Options, } -/// Optional `space_or_tab` +/// One or more `space_or_tab`. /// /// ```bnf -/// space_or_tab_opt ::= *( ' ' '\t' ) +/// space_or_tab ::= 1*( ' ' '\t' ) /// ``` -pub fn space_or_tab_opt() -> Box { - space_or_tab_min_max(0, usize::MAX) +pub fn space_or_tab() -> Box { + space_or_tab_min_max(1, usize::MAX) } /// Between `x` and `y` `space_or_tab` @@ -34,7 +41,11 @@ pub fn space_or_tab_opt() -> Box { /// space_or_tab_min_max ::= x*y( ' ' '\t' ) /// ``` pub fn space_or_tab_min_max(min: usize, max: usize) -> Box { - space_or_tab(TokenType::SpaceOrTab, min, max) + space_or_tab_with_options(Options { + kind: TokenType::SpaceOrTab, + min, + max, + }) } /// Between `x` and `y` `space_or_tab`, with the given token type. @@ -42,14 +53,8 @@ pub fn space_or_tab_min_max(min: usize, max: usize) -> Box { /// ```bnf /// space_or_tab ::= x*y( ' ' '\t' ) /// ``` -pub fn space_or_tab(kind: TokenType, min: usize, max: usize) -> Box { - let info = Info { - size: 0, - min, - max, - kind, - }; - Box::new(|t, c| start(t, c, info)) +pub fn space_or_tab_with_options(options: Options) -> Box { + Box::new(|t, c| start(t, c, Info { size: 0, options })) } /// Before whitespace. @@ -59,14 +64,18 @@ pub fn space_or_tab(kind: TokenType, min: usize, max: usize) -> Box { /// ``` fn start(tokenizer: &mut Tokenizer, code: Code, mut info: Info) -> StateFnResult { match code { - Code::VirtualSpace | Code::Char('\t' | ' ') if info.max > 0 => { - tokenizer.enter(info.kind.clone()); + Code::VirtualSpace | Code::Char('\t' | ' ') if info.options.max > 0 => { + tokenizer.enter(info.options.kind.clone()); tokenizer.consume(code); info.size += 1; (State::Fn(Box::new(|t, c| inside(t, c, info))), None) } _ => ( - if info.min == 0 { State::Ok } else { State::Nok }, + if info.options.min == 0 { + State::Ok + } else { + State::Nok + }, Some(vec![code]), ), } @@ -80,15 +89,15 @@ fn start(tokenizer: &mut Tokenizer, code: Code, mut info: Info) -> StateFnResult /// ``` fn inside(tokenizer: &mut Tokenizer, code: Code, mut info: Info) -> StateFnResult { match code { - Code::VirtualSpace | Code::Char('\t' | ' ') if info.size < info.max => { + Code::VirtualSpace | Code::Char('\t' | ' ') if info.size < info.options.max => { tokenizer.consume(code); info.size += 1; (State::Fn(Box::new(|t, c| inside(t, c, info))), None) } _ => { - tokenizer.exit(info.kind.clone()); + tokenizer.exit(info.options.kind.clone()); ( - if info.size >= info.min { + if info.size >= info.options.min { State::Ok } else { State::Nok -- cgit