replace-megaparsec 1.1.3.0 → 1.1.4.0
raw patch · 2 files changed
+83/−24 lines, 2 files
Files
- README.md +82/−23
- replace-megaparsec.cabal +1/−1
README.md view
@@ -4,6 +4,11 @@ [](http://stackage.org/nightly/package/replace-megaparsec) [](http://stackage.org/lts/package/replace-megaparsec) +* [Usage Examples](#usage-examples)+* [In the Shell](#in-the-shell)+* [Alternatives](#alternatives)+* [Hypothetically Asked Questions](#hypothetically-asked-questions)+ __replace-megaparsec__ is for finding text patterns, and also editing and replacing the found patterns. This activity is traditionally done with regular expressions,@@ -32,7 +37,7 @@ See [__replace-attoparsec__](https://hackage.haskell.org/package/replace-attoparsec) for the [__attoparsec__](http://hackage.haskell.org/package/attoparsec)-version.+version. ([__megaparsec__ is as fast as __attoparsec__](https://github.com/mrkkrp/megaparsec#performance)). ## Why would we want to do pattern matching and substitution with parsers instead of regular expressions? @@ -72,7 +77,7 @@ this library, instead of a template, we get an `editor` function which can perform any computation, including IO. -## Examples+# Usage Examples Try the examples in `ghci` by running `cabal v2-repl` in the `replace-megaparsec/`@@ -87,13 +92,13 @@ import Text.Megaparsec.Char.Lexer ``` -### Parsing with `sepCap` family of parser combinators+## Parsing with `sepCap` family of parser combinators The following examples show how to match a pattern to a string of text and deconstruct the string of text by separating it into sections which match the pattern, and sections which don't match. -#### Pattern match, capture only the parsed result with `sepCap`+### Pattern match, capture only the parsed result with `sepCap` Separate the input string into sections which can be parsed as a hexadecimal number with a prefix `"0x"`, and sections which can't.@@ -106,7 +111,7 @@ [Right 10,Left " 000 ",Right 65535] ``` -#### Pattern match, capture only the matched text with `findAll`+### Pattern match, capture only the matched text with `findAll` Just get the strings sections which match the hexadecimal parser, throw away the parsed number.@@ -119,7 +124,7 @@ [Right "0xA",Left " 000 ",Right "0xFFFF"] ``` -#### Pattern match, capture the matched text and the parsed result with `findAllCap`+### Pattern match, capture the matched text and the parsed result with `findAllCap` Capture the parsed hexadecimal number, as well as the string section which parses as a hexadecimal number.@@ -132,7 +137,7 @@ [Right ("0xA",10),Left " 000 ",Right ("0xFFFF",65535)] ``` -#### Pattern match, capture only the locations of the matched patterns+### Pattern match, capture only the locations of the matched patterns Find all of the sections of the stream which match a string of spaces.@@ -147,7 +152,7 @@ [0,2,5] ``` -#### Pattern match balanced parentheses+### Pattern match balanced parentheses Find the outer parentheses of all balanced nested parentheses. Here's an example of matching a pattern that can't be expressed by a regular@@ -168,13 +173,13 @@ [Right "(())",Left " ",Right "(()())"] ``` -### Edit text strings by running parsers with `streamEdit`+## Edit text strings by running parsers with `streamEdit` The following examples show how to search for a pattern in a string of text and then edit the string of text to substitute in some replacement text for the matched patterns. -#### Pattern match and replace with a constant+### Pattern match and replace with a constant Replace all carriage-return-newline instances with newline. @@ -185,7 +190,7 @@ "1\n2\n" ``` -#### Pattern match and edit the matches+### Pattern match and edit the matches Replace alphabetic characters with the next character in the alphabet. @@ -196,7 +201,7 @@ "IBM 9000" ``` -#### Pattern match and maybe edit the matches, or maybe leave them alone+### Pattern match and maybe edit the matches, or maybe leave them alone Find all of the string sections *`s`* which can be parsed as a hexadecimal number *`r`*,@@ -206,14 +211,17 @@ ```haskell let hexparser = chunk "0x" >> hexadecimal :: Parsec Void String Integer-streamEdit (match hexparser) (\(s,r) -> if r <= 16 then show r else s) "0xA 000 0xFFFF"+streamEdit (match hexparser) (\(s,r) -> if r<=16 then show r else s) "0xA 000 0xFFFF" ``` ```haskell "10 000 0xFFFF" ``` -#### Pattern match and edit the matches with IO+### Pattern match and edit the matches with IO +Find an environment variable in curly braces and replace it with its+value from the environment.+ ```haskell import System.Environment streamEditT (char '{' *> manyTill anySingle (char '}')) getEnv "- {HOME} -"@@ -222,7 +230,7 @@ "- /home/jbrock -" ``` -#### Context-sensitive pattern match and edit the matches+### Context-sensitive pattern match and edit the matches Capitalize the third letter in a string. The `capthird` parser searches for individual letters, and it needs to remember how many times it has run so@@ -249,8 +257,49 @@ "a a A a a" ``` -## Alternatives+# In the Shell +If we're going to have a viable `sed` replacement then we want to be able+to use it easily from the command line. This script uses the+[Stack script interpreter](https://docs.haskellstack.org/en/stable/GUIDE/#script-interpreter)+To find decimal numbers in a stream and replace them with their double.++```haskell+#!/usr/bin/env stack+{- stack+ script+ --resolver nightly-2019-09-13+ --package megaparsec+ --package replace-megaparsec+-}+-- https://docs.haskellstack.org/en/stable/GUIDE/#script-interpreter++import Text.Megaparsec+import Text.Megaparsec.Char+import Text.Megaparsec.Char.Lexer+import Replace.Megaparsec++main = interact $ streamEdit decimal (show . (*2))+```++If you have+[The Haskell Tool Stack](https://docs.haskellstack.org/en/stable/README/)+installed then you can just copy-paste this into a file named `script.hs` and+run it. (On the first run Stack may need to download the dependencies.)++```bash+$ chmod u+x script.hs+$ echo "1 6 21 107" | ./script.hs+2 12 42 214+```+++# Alternatives++Some libraries that one might consider instead of this one.++<http://hackage.haskell.org/package/regex-applicative>+ <http://hackage.haskell.org/package/regex> <http://hackage.haskell.org/package/pipes-parse>@@ -263,9 +312,7 @@ <http://hackage.haskell.org/package/template> -<http://hackage.haskell.org/package/regex-applicative>--## Hypothetically Asked Questions+# Hypothetically Asked Questions 1. *Is it fast?* @@ -299,8 +346,20 @@ combinator doesn't exist for __parsec__. (I can't find it anywhere. [Can it be written?](http://www.serpentine.com/blog/2014/05/31/attoparsec/#from-strings-to-buffers-and-cursors)) -3. *Could we write this library for __attoparsec__?*+3. *Is this a good idea?* - I think so, but I wouldn't expect much of a speed improvement, because- again, `sepCap` is a fundamentally slow activity, and anyway- [__megaparsec__ is as fast as __attoparsec__](https://github.com/mrkkrp/megaparsec#performance).+ You may have heard it suggested that monadic parsers are better when+ the input stream is mostly signal, and regular expressions are better+ when the input stream is mostly noise.++ The premise of this library is:+ that sentiment is outdated; monadic parsers are great for finding+ small patterns in a stream of otherwise uninteresting text; and the+ reluctance to forego the speedup opportunities afforded by restricting+ ourselves to regular grammars is an old superstition about+ opportunities which+ [remain mostly unexploited anyway](https://swtch.com/~rsc/regexp/regexp1.html).+ The performance compromise of allowing stack memory allocation (a.k.a pushdown+ automata, a.k.a context-free grammar) was once considered+ [controversial for *general-purpose* programming languages](https://vanemden.wordpress.com/2014/06/18/how-recursion-got-into-programming-a-comedy-of-errors-3/). I think we+ can now resolve that controversy the same way for pattern matching languages.
replace-megaparsec.cabal view
@@ -1,5 +1,5 @@ name: replace-megaparsec-version: 1.1.3.0+version: 1.1.4.0 cabal-version: 1.18 synopsis: Stream edit, find-and-replace with Megaparsec parsers homepage: https://github.com/jamesdbrock/replace-megaparsec