Introduce a matcher for one or more matched digits
This commit is contained in:
parent
74da0eb391
commit
3dde41e0d4
@ -62,8 +62,8 @@ data MatchState = MatchState
|
|||||||
data MatchToken
|
data MatchToken
|
||||||
= OpenParenMatchToken
|
= OpenParenMatchToken
|
||||||
| CloseParenMatchToken
|
| CloseParenMatchToken
|
||||||
| AsteriskMatchToken
|
|
||||||
| SymbolMatchToken Char
|
| SymbolMatchToken Char
|
||||||
|
| AtLeastMatchToken [Char]
|
||||||
| OneOfMatchToken [Char]
|
| OneOfMatchToken [Char]
|
||||||
deriving (Eq, Show)
|
deriving (Eq, Show)
|
||||||
|
|
||||||
@ -76,6 +76,7 @@ data MatchToken
|
|||||||
-- * ( ) - The text in parentheses is matched but no saved in the resulting
|
-- * ( ) - The text in parentheses is matched but no saved in the resulting
|
||||||
-- string.
|
-- string.
|
||||||
-- * \\d - Matches zero or more digits.
|
-- * \\d - Matches zero or more digits.
|
||||||
|
-- * \\D - Matches one or more digits.
|
||||||
-- * \\. - Matches zero or more digits or dots.
|
-- * \\. - Matches zero or more digits or dots.
|
||||||
-- * \\\\ - Matches a back slash.
|
-- * \\\\ - Matches a back slash.
|
||||||
-- * * - Matches everything.
|
-- * * - Matches everything.
|
||||||
@ -103,20 +104,21 @@ match fullPattern = go startState
|
|||||||
go (state{ ignoring = True, pattern' = tokens }) input'
|
go (state{ ignoring = True, pattern' = tokens }) input'
|
||||||
go state@MatchState{ pattern' = CloseParenMatchToken : tokens } input' =
|
go state@MatchState{ pattern' = CloseParenMatchToken : tokens } input' =
|
||||||
go (state{ ignoring = False, pattern' = tokens }) input'
|
go (state{ ignoring = False, pattern' = tokens }) input'
|
||||||
go state@MatchState{ pattern' = AsteriskMatchToken : tokens } input'
|
go state@MatchState{ pattern' = SymbolMatchToken patternCharacter : tokens } input'
|
||||||
| Just (nextCharacter, leftOver) <- Text.uncons input' =
|
| Just (nextCharacter, leftOver) <- Text.uncons input'
|
||||||
go (matchSymbolToken state nextCharacter) leftOver
|
, patternCharacter == nextCharacter =
|
||||||
| otherwise = go state{ pattern' = tokens } ""
|
go (matchSymbolToken state{ pattern' = tokens } nextCharacter) leftOver
|
||||||
|
| otherwise = Nothing
|
||||||
go state@MatchState{ pattern' = OneOfMatchToken chars : tokens } input'
|
go state@MatchState{ pattern' = OneOfMatchToken chars : tokens } input'
|
||||||
| Just (nextCharacter, leftOver) <- Text.uncons input'
|
| Just (nextCharacter, leftOver) <- Text.uncons input'
|
||||||
, nextCharacter `elem` chars =
|
, nextCharacter `elem` chars =
|
||||||
go (matchSymbolToken state nextCharacter) leftOver
|
go (matchSymbolToken state nextCharacter) leftOver
|
||||||
| otherwise =
|
| otherwise =
|
||||||
go (state{ pattern' = tokens }) input'
|
go (state{ pattern' = tokens }) input'
|
||||||
go state@MatchState{ pattern' = SymbolMatchToken patternCharacter : tokens } input'
|
go state@MatchState{ pattern' = AtLeastMatchToken chars : tokens } input'
|
||||||
| Just (nextCharacter, leftOver) <- Text.uncons input'
|
| Just (nextCharacter, leftOver) <- Text.uncons input'
|
||||||
, patternCharacter == nextCharacter =
|
, nextCharacter `elem` chars =
|
||||||
go (matchSymbolToken state{ pattern' = tokens } nextCharacter) leftOver
|
go (matchSymbolToken state{ pattern' = OneOfMatchToken chars : tokens } nextCharacter) leftOver
|
||||||
| otherwise = Nothing
|
| otherwise = Nothing
|
||||||
-- All tokens are processed, but there is still some input left.
|
-- All tokens are processed, but there is still some input left.
|
||||||
go MatchState{ pattern' = [] } _ = Nothing
|
go MatchState{ pattern' = [] } _ = Nothing
|
||||||
@ -134,7 +136,9 @@ parsePattern input'
|
|||||||
Nothing -> []
|
Nothing -> []
|
||||||
Just ('d', remaining') -> OneOfMatchToken digits
|
Just ('d', remaining') -> OneOfMatchToken digits
|
||||||
: parsePattern remaining'
|
: parsePattern remaining'
|
||||||
Just ('.', remaining') -> OneOfMatchToken ('.' : digits)
|
Just ('D', remaining') -> AtLeastMatchToken digits
|
||||||
|
: parsePattern remaining'
|
||||||
|
Just ('.', remaining') -> AtLeastMatchToken ('.' : digits)
|
||||||
: parsePattern remaining'
|
: parsePattern remaining'
|
||||||
Just ('\\', remaining') -> SymbolMatchToken '\\'
|
Just ('\\', remaining') -> SymbolMatchToken '\\'
|
||||||
: parsePattern remaining'
|
: parsePattern remaining'
|
||||||
@ -147,7 +151,7 @@ parsePattern input'
|
|||||||
| Just (firstChar, remaining) <- Text.uncons input' =
|
| Just (firstChar, remaining) <- Text.uncons input' =
|
||||||
let token =
|
let token =
|
||||||
case firstChar of
|
case firstChar of
|
||||||
'*' -> AsteriskMatchToken
|
'*' -> OneOfMatchToken (toEnum <$> [32 .. 127])
|
||||||
'(' -> OpenParenMatchToken
|
'(' -> OpenParenMatchToken
|
||||||
')' -> CloseParenMatchToken
|
')' -> CloseParenMatchToken
|
||||||
s -> SymbolMatchToken s
|
s -> SymbolMatchToken s
|
||||||
|
@ -27,7 +27,7 @@ spec = do
|
|||||||
actual = match "(v)2.6.\\d" "v2.6.0"
|
actual = match "(v)2.6.\\d" "v2.6.0"
|
||||||
in actual `shouldBe` expected
|
in actual `shouldBe` expected
|
||||||
|
|
||||||
it "matches digits and dot" $
|
it "matches digits and dots" $
|
||||||
let expected = Just "2.6.0"
|
let expected = Just "2.6.0"
|
||||||
actual = match "(v)\\." "v2.6.0"
|
actual = match "(v)\\." "v2.6.0"
|
||||||
in actual `shouldBe` expected
|
in actual `shouldBe` expected
|
||||||
@ -46,3 +46,8 @@ spec = do
|
|||||||
let expected = Just "abc"
|
let expected = Just "abc"
|
||||||
actual = match "abc\\d\\d" "abc"
|
actual = match "abc\\d\\d" "abc"
|
||||||
in actual `shouldBe` expected
|
in actual `shouldBe` expected
|
||||||
|
|
||||||
|
it "matches at least one digit" $
|
||||||
|
let expected = Nothing
|
||||||
|
actual = match "1.\\D.3" "1..3"
|
||||||
|
in actual `shouldBe` expected
|
||||||
|
Loading…
Reference in New Issue
Block a user