better presentation
This commit is contained in:
parent
282012720d
commit
87ae01adc8
25 changed files with 561 additions and 106 deletions
110
parsec.html
110
parsec.html
|
@ -108,15 +108,23 @@
|
|||
</blockquote>
|
||||
</section>
|
||||
<section class="slide">
|
||||
<h2 id="parsecs">Parsec(s)</h2>
|
||||
<p>In reality there is many choices:</p>
|
||||
<pre><code>- attoparsec: fast
|
||||
- Bytestring-lexing: fast
|
||||
- Parsec 3: powerful, nice error reporting</code></pre>
|
||||
</section>
|
||||
<section class="slide">
|
||||
<h2 id="a-parsec-example">A Parsec Example</h2>
|
||||
<pre class="sourceCode haskell"><code class="sourceCode haskell">whitespaces <span class="fu">=</span> many (oneOf <span class="st">"\t "</span>)
|
||||
number <span class="fu">=</span> many1 digit</code></pre>
|
||||
<pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="dt">Right</span> <span class="st">" \t "</span> <span class="co">-- whitespaces on " \t "</span>
|
||||
<span class="dt">Right</span> <span class="st">""</span> <span class="co">-- whitespaces on "32"</span>
|
||||
<span class="dt">Right</span> <span class="st">"32"</span> <span class="co">-- number on "32"</span>
|
||||
number <span class="fu">=</span> many1 digit
|
||||
symbol <span class="fu">=</span> oneOf <span class="st">"!#$%<span class="and">&</span>|*+-/:<=>?@^_~"</span></code></pre>
|
||||
<pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="st">" \t "</span> <span class="co">-- whitespaces on " \t "</span>
|
||||
<span class="st">""</span> <span class="co">-- whitespaces on "32"</span>
|
||||
<span class="st">"32"</span> <span class="co">-- number on "32"</span>
|
||||
|
||||
<span class="co">-- number on " \t 32 "</span>
|
||||
<span class="dt">Left</span> <span class="st">"number"</span> (line <span class="dv">1</span>, column <span class="dv">1</span>)<span class="fu">:</span>
|
||||
<span class="st">"number"</span> (line <span class="dv">1</span>, column <span class="dv">1</span>)<span class="fu">:</span>
|
||||
unexpected <span class="st">" "</span>
|
||||
expecting digit</code></pre>
|
||||
</section>
|
||||
|
@ -128,19 +136,93 @@ number <span class="fu">=</span> many1 digit
|
|||
<span class="ot">number' ::</span> <span class="dt">Parser</span> <span class="dt">Int</span>
|
||||
number' <span class="fu">=</span> <span class="kw">do</span>
|
||||
string_of_number <span class="ot"><-</span> many1 digit
|
||||
return (read string_of_number)</code></pre>
|
||||
<span class="fu">return</span> (<span class="fu">read</span> string_of_number)</code></pre>
|
||||
<pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="st">"32"</span><span class="ot"> ::</span> [<span class="dt">Char</span>] <span class="co">-- number on "32"</span>
|
||||
<span class="dv">32</span><span class="ot"> ::</span> <span class="dt">Int</span> <span class="co">-- number' on "32"</span></code></pre>
|
||||
</section>
|
||||
<section class="slide">
|
||||
<h2 id="monadic-style">Monadic style</h2>
|
||||
<pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="ot">isolatedNumber ::</span> <span class="dt">Parser</span> <span class="dt">String</span>
|
||||
isolatedNumber <span class="fu">=</span> <span class="kw">do</span>
|
||||
_ <span class="ot"><-</span> whitespaces
|
||||
n <span class="ot"><-</span> number
|
||||
_ <span class="ot"><-</span> whitespaces
|
||||
return n</code></pre>
|
||||
<pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="dt">Right</span> <span class="st">"32"</span> <span class="co">-- isolatedNumber on " \t 32 "</span></code></pre>
|
||||
<h2 id="combining-monadic-style">Combining Monadic style</h2>
|
||||
<p><br /><span class="math"><em>S</em> = <em>a</em><em>S</em><em>b</em>∣<em>ε</em></span><br /></p>
|
||||
<pre class="sourceCode haskell"><code class="sourceCode haskell">s <span class="fu">=</span> (<span class="kw">do</span>
|
||||
a <span class="ot"><-</span> char <span class="ch">'a'</span>
|
||||
mid <span class="ot"><-</span> <span class="dt">S</span>
|
||||
b <span class="ot"><-</span> char <span class="ch">'b'</span>
|
||||
<span class="fu">return</span> (a<span class="fu">:</span>mid) <span class="fu">++</span> b<span class="fu">:</span>[])
|
||||
<span class="fu"><|></span> string <span class="st">""</span></code></pre>
|
||||
<pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="st">""</span> <span class="co">-- s on ""</span>
|
||||
<span class="st">"aaabbb"</span> <span class="co">-- s on "aaabbb"</span>
|
||||
<span class="st">"aabb"</span> <span class="co">-- s on "aabbb"</span>
|
||||
<span class="co">-- s on "aaabb"</span>
|
||||
<span class="dt">S</span> (line1 <span class="dv">1</span>, column <span class="dv">4</span>)<span class="fu">:</span>
|
||||
unexpected end <span class="kw">of</span> input
|
||||
expecting <span class="st">"b"</span></code></pre>
|
||||
</section>
|
||||
<section class="slide">
|
||||
<h2 id="applicative-style">Applicative style</h2>
|
||||
<p><br /><span class="math"><em>S</em> = <em>a</em><em>S</em><em>b</em>∣<em>ε</em></span><br /></p>
|
||||
<pre class="sourceCode haskell"><code class="sourceCode haskell">s <span class="fu">=</span> concat3 <span class="fu"><$></span> string <span class="st">"a"</span> <span class="fu"><*></span> s <span class="fu"><*></span> char <span class="st">"b"</span>
|
||||
<span class="fu"><|></span> string <span class="st">""</span>
|
||||
<span class="kw">where</span>
|
||||
concat3 x y z <span class="fu">=</span> x <span class="fu">++</span> y <span class="fu">++</span> z</code></pre>
|
||||
</section>
|
||||
<section class="slide">
|
||||
<h2 id="applicative-style-usefull-with-data-types">Applicative Style usefull with Data types</h2>
|
||||
<pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="kw">data</span> <span class="dt">IP</span> <span class="fu">=</span> <span class="dt">IP</span> <span class="dt">Int</span> <span class="dt">Int</span> <span class="dt">Int</span> <span class="dt">Int</span>
|
||||
|
||||
parseIP <span class="fu">=</span> <span class="dt">IP</span> <span class="fu"><$></span>
|
||||
number <span class="fu"><*</span> char <span class="ch">'.'</span> <span class="fu"><*></span>
|
||||
number <span class="fu"><*</span> char <span class="ch">'.'</span> <span class="fu"><*></span>
|
||||
number <span class="fu"><*</span> char <span class="ch">'.'</span> <span class="fu"><*></span>
|
||||
number
|
||||
|
||||
monadicParseIP <span class="fu">=</span> <span class="kw">do</span>
|
||||
d1 <span class="ot"><-</span> number
|
||||
char <span class="ch">'.'</span>
|
||||
d2 <span class="ot"><-</span> number
|
||||
char <span class="ch">'.'</span>
|
||||
d3 <span class="ot"><-</span> number
|
||||
char <span class="ch">'.'</span>
|
||||
d4 <span class="ot"><-</span> number
|
||||
<span class="fu">return</span> (<span class="dt">IP</span> d1 d2 d3 d4)</code></pre>
|
||||
</section>
|
||||
<section class="slide">
|
||||
<h2 id="write-number-correctly">Write number correctly</h2>
|
||||
<pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="ot">number ::</span> <span class="dt">Parser</span> <span class="dt">Int</span>
|
||||
number <span class="fu">=</span> <span class="kw">do</span>
|
||||
x <span class="ot"><-</span> <span class="fu">read</span> <span class="fu"><$></span> many1 digit
|
||||
guard (<span class="dv">0</span> <span class="fu"><=</span> x <span class="fu"><span class="and">&</span><span class="and">&</span></span> x <span class="fu"><</span> <span class="dv">256</span>) <span class="fu"><?></span>
|
||||
<span class="st">"Number between 0 and 255 (here "</span> <span class="fu">++</span> <span class="fu">show</span> x <span class="fu">++</span> <span class="st">")"</span>
|
||||
<span class="fu">return</span> (<span class="fu">fromIntegral</span> x)</code></pre>
|
||||
<pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="fu">>>></span> test parseIP <span class="st">"parseIP"</span> <span class="st">"823.32.80.113"</span>
|
||||
<span class="st">"parseIP"</span> (line <span class="dv">1</span>, column <span class="dv">4</span>)<span class="fu">:</span>
|
||||
unexpected <span class="st">"."</span>
|
||||
expecting digit <span class="fu">or</span> <span class="dt">Number</span> between <span class="dv">0</span> <span class="fu">and</span> <span class="dv">255</span> (here <span class="dv">823</span>)</code></pre>
|
||||
</section>
|
||||
<section class="slide">
|
||||
<h2 id="so">So</h2>
|
||||
<ul>
|
||||
<li>combination of simple parsers</li>
|
||||
<li>error messages with <code>(<?>)</code></li>
|
||||
<li>embed result in data type using Applicative style</li>
|
||||
<li>Not shown, use another monad with the parser</li>
|
||||
</ul>
|
||||
<p>Time to do something cool</p>
|
||||
</section>
|
||||
<section class="slide">
|
||||
<h2 id="a-simple-dsl">A Simple DSL</h2>
|
||||
<p>Let's write a minimal DSL</p>
|
||||
</section>
|
||||
<section class="slide">
|
||||
<h2 id="useful-definitions">Useful definitions</h2>
|
||||
<p><code>try</code> tries to parse and backtracks if it fails.</p>
|
||||
<pre class="sourceCode haskell"><code class="sourceCode haskell">(<span class="fu"><||></span>) parser1 parser2 <span class="fu">=</span> try parser1 <span class="fu"><|></span> parser2</code></pre>
|
||||
<p><code>lexeme</code>, just skip spaces.</p>
|
||||
<pre class="sourceCode haskell"><code class="sourceCode haskell">lexeme parser <span class="fu">=</span> whitespaces <span class="fu">*></span> parser <span class="fu"><*</span> whitespaces</code></pre>
|
||||
</section>
|
||||
<section class="slide">
|
||||
<h2 id="data-structure">Data Structure</h2>
|
||||
<p>Remember from text to data structure</p>
|
||||
<pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="kw">data</span> <span class="dt">Tree</span> <span class="fu">=</span> <span class="dt">Node</span> <span class="dt">Element</span> [<span class="dt">Tree</span>]</code></pre>
|
||||
</section>
|
||||
<!-- End slides. -->
|
||||
|
||||
|
|
BIN
parsec/10_Introduction/.030_advanced.md.swp
Normal file
BIN
parsec/10_Introduction/.030_advanced.md.swp
Normal file
Binary file not shown.
147
parsec/10_Introduction/020_intro.md
Normal file
147
parsec/10_Introduction/020_intro.md
Normal file
|
@ -0,0 +1,147 @@
|
|||
## Parsing
|
||||
|
||||
Latin pars (ōrātiōnis), meaning part (of speech).
|
||||
|
||||
- **analysing a string of symbols**
|
||||
- **formal grammar**.
|
||||
|
||||
## Parsing Example (1)
|
||||
|
||||
From String:
|
||||
|
||||
``` haskell
|
||||
(1+3)*(1+5+9)
|
||||
```
|
||||
|
||||
To data structure:
|
||||
|
||||
![AST](parsec/img/mp/AST.png)\
|
||||
|
||||
## Parsec
|
||||
|
||||
> Parsec lets you construct parsers by combining high-order Combinators
|
||||
> to create larger expressions.
|
||||
>
|
||||
> Combinator parsers are written and used within the same programming language
|
||||
> as the rest of the program.
|
||||
>
|
||||
> The parsers are first-class citizens of the languages [...]"
|
||||
|
||||
## Parsec(s)
|
||||
|
||||
In reality there is many choices:
|
||||
|
||||
- attoparsec: fast
|
||||
- Bytestring-lexing: fast
|
||||
- Parsec 3: powerful, nice error reporting
|
||||
|
||||
## A Parsec Example
|
||||
|
||||
``` haskell
|
||||
whitespaces = many (oneOf "\t ")
|
||||
number = many1 digit
|
||||
symbol = oneOf "!#$%&|*+-/:<=>?@^_~"
|
||||
```
|
||||
|
||||
``` haskell
|
||||
" \t " -- whitespaces on " \t "
|
||||
"" -- whitespaces on "32"
|
||||
"32" -- number on "32"
|
||||
|
||||
-- number on " \t 32 "
|
||||
"number" (line 1, column 1):
|
||||
unexpected " "
|
||||
expecting digit
|
||||
```
|
||||
|
||||
## Monadic style
|
||||
|
||||
``` haskell
|
||||
number :: Parser String
|
||||
number = many1 digit
|
||||
|
||||
number' :: Parser Int
|
||||
number' = do
|
||||
string_of_number <- many1 digit
|
||||
return (read string_of_number)
|
||||
```
|
||||
|
||||
``` haskell
|
||||
"32" :: [Char] -- number on "32"
|
||||
32 :: Int -- number' on "32"
|
||||
```
|
||||
|
||||
## Combining Monadic style
|
||||
|
||||
$$ S = aSb | ε $$
|
||||
|
||||
``` haskell
|
||||
s = (do
|
||||
a <- char 'a'
|
||||
mid <- S
|
||||
b <- char 'b'
|
||||
return (a:mid) ++ b:[])
|
||||
<|> string ""
|
||||
|
||||
```
|
||||
|
||||
``` haskell
|
||||
"" -- s on ""
|
||||
"aaabbb" -- s on "aaabbb"
|
||||
"aabb" -- s on "aabbb"
|
||||
-- s on "aaabb"
|
||||
S (line1 1, column 4):
|
||||
unexpected end of input
|
||||
expecting "b"
|
||||
```
|
||||
|
||||
## Applicative style
|
||||
|
||||
$$ S = aSb | ε $$
|
||||
|
||||
``` haskell
|
||||
s = concat3 <$> string "a" <*> s <*> char "b"
|
||||
<|> string ""
|
||||
where
|
||||
concat3 x y z = x ++ y ++ z
|
||||
```
|
||||
|
||||
## Applicative Style usefull with Data types
|
||||
|
||||
``` haskell
|
||||
data IP = IP Int Int Int Int
|
||||
|
||||
parseIP = IP <$>
|
||||
number <* char '.' <*>
|
||||
number <* char '.' <*>
|
||||
number <* char '.' <*>
|
||||
number
|
||||
|
||||
monadicParseIP = do
|
||||
d1 <- number
|
||||
char '.'
|
||||
d2 <- number
|
||||
char '.'
|
||||
d3 <- number
|
||||
char '.'
|
||||
d4 <- number
|
||||
return (IP d1 d2 d3 d4)
|
||||
```
|
||||
|
||||
## Write number correctly
|
||||
|
||||
``` haskell
|
||||
number :: Parser Int
|
||||
number = do
|
||||
x <- read <$> many1 digit
|
||||
guard (0 <= x && x < 256) <?>
|
||||
"Number between 0 and 255 (here " ++ show x ++ ")"
|
||||
return (fromIntegral x)
|
||||
```
|
||||
|
||||
``` haskell
|
||||
>>> test parseIP "parseIP" "823.32.80.113"
|
||||
"parseIP" (line 1, column 4):
|
||||
unexpected "."
|
||||
expecting digit or Number between 0 and 255 (here 823)
|
||||
```
|
34
parsec/10_Introduction/030_advanced.md
Normal file
34
parsec/10_Introduction/030_advanced.md
Normal file
|
@ -0,0 +1,34 @@
|
|||
## So
|
||||
|
||||
- combination of simple parsers
|
||||
- error messages with `(<?>)`
|
||||
- embed result in data type using Applicative style
|
||||
- Not shown, use another monad with the parser
|
||||
|
||||
Time to do something cool
|
||||
|
||||
## A Simple DSL
|
||||
|
||||
Let's write a minimal DSL
|
||||
|
||||
## Useful definitions
|
||||
|
||||
`try` tries to parse and backtracks if it fails.
|
||||
|
||||
``` haskell
|
||||
(<||>) parser1 parser2 = try parser1 <|> parser2
|
||||
```
|
||||
|
||||
`lexeme`, just skip spaces.
|
||||
|
||||
``` haskell
|
||||
lexeme parser = whitespaces *> parser <* whitespaces
|
||||
```
|
||||
|
||||
## Data Structure
|
||||
|
||||
Remember from text to data structure
|
||||
|
||||
``` haskell
|
||||
data Tree = Node Element [Tree]
|
||||
```
|
|
@ -1,19 +0,0 @@
|
|||
## [Write Yourself a Scheme in 48 Hours](https://en.wikibooks.org/wiki/Write_Yourself_a_Scheme_in_48_Hours/First_Steps)
|
||||
|
||||
|
||||
~~~ {.haskell}
|
||||
import Text.Parsec
|
||||
type Parser a = Parsec String () a
|
||||
~~~
|
||||
|
||||
~~~ {.haskell}
|
||||
symbol :: Parser Char
|
||||
symbol = oneOf "!#$%&|*+-/:<=>?@^_~"
|
||||
~~~
|
||||
|
||||
~~~ {.haskell}
|
||||
readExpr :: String -> String
|
||||
readExpr input = case parse symbol "lisp" input of
|
||||
Left err -> "No match: " ++ show err
|
||||
Right val -> "Found: " ++ show val
|
||||
~~~
|
|
@ -1,14 +0,0 @@
|
|||
## Monadic style
|
||||
|
||||
``` haskell
|
||||
isolatedNumber :: Parser String
|
||||
isolatedNumber = do
|
||||
_ <- whitespaces
|
||||
n <- number
|
||||
_ <- whitespaces
|
||||
return n
|
||||
```
|
||||
|
||||
``` haskell
|
||||
Right "32" -- isolatedNumber on " \t 32 "
|
||||
```
|
|
@ -1,7 +1,7 @@
|
|||
## Parsing
|
||||
|
||||
|
||||
Latin pars (ōrātiōnis), meaning part (of speech).
|
||||
|
||||
- **analysing a string of symbols**
|
||||
- **formal grammar**.
|
||||
|
|
@ -9,3 +9,4 @@ From String:
|
|||
To data structure:
|
||||
|
||||
![AST](parsec/img/mp/AST.png)\
|
||||
|
|
@ -7,3 +7,4 @@
|
|||
> as the rest of the program.
|
||||
>
|
||||
> The parsers are first-class citizens of the languages [...]"
|
||||
|
8
parsec/_tmp/10_Introduction/020_intro-003.md
Normal file
8
parsec/_tmp/10_Introduction/020_intro-003.md
Normal file
|
@ -0,0 +1,8 @@
|
|||
## Parsec(s)
|
||||
|
||||
In reality there is many choices:
|
||||
|
||||
- attoparsec: fast
|
||||
- Bytestring-lexing: fast
|
||||
- Parsec 3: powerful, nice error reporting
|
||||
|
|
@ -3,15 +3,17 @@
|
|||
``` haskell
|
||||
whitespaces = many (oneOf "\t ")
|
||||
number = many1 digit
|
||||
symbol = oneOf "!#$%&|*+-/:<=>?@^_~"
|
||||
```
|
||||
|
||||
``` haskell
|
||||
Right " \t " -- whitespaces on " \t "
|
||||
Right "" -- whitespaces on "32"
|
||||
Right "32" -- number on "32"
|
||||
" \t " -- whitespaces on " \t "
|
||||
"" -- whitespaces on "32"
|
||||
"32" -- number on "32"
|
||||
|
||||
-- number on " \t 32 "
|
||||
Left "number" (line 1, column 1):
|
||||
"number" (line 1, column 1):
|
||||
unexpected " "
|
||||
expecting digit
|
||||
```
|
||||
|
|
@ -14,3 +14,4 @@ number' = do
|
|||
"32" :: [Char] -- number on "32"
|
||||
32 :: Int -- number' on "32"
|
||||
```
|
||||
|
24
parsec/_tmp/10_Introduction/020_intro-006.md
Normal file
24
parsec/_tmp/10_Introduction/020_intro-006.md
Normal file
|
@ -0,0 +1,24 @@
|
|||
## Combining Monadic style
|
||||
|
||||
$$ S = aSb | ε $$
|
||||
|
||||
``` haskell
|
||||
s = (do
|
||||
a <- char 'a'
|
||||
mid <- S
|
||||
b <- char 'b'
|
||||
return (a:mid) ++ b:[])
|
||||
<|> string ""
|
||||
|
||||
```
|
||||
|
||||
``` haskell
|
||||
"" -- s on ""
|
||||
"aaabbb" -- s on "aaabbb"
|
||||
"aabb" -- s on "aabbb"
|
||||
-- s on "aaabb"
|
||||
S (line1 1, column 4):
|
||||
unexpected end of input
|
||||
expecting "b"
|
||||
```
|
||||
|
11
parsec/_tmp/10_Introduction/020_intro-007.md
Normal file
11
parsec/_tmp/10_Introduction/020_intro-007.md
Normal file
|
@ -0,0 +1,11 @@
|
|||
## Applicative style
|
||||
|
||||
$$ S = aSb | ε $$
|
||||
|
||||
``` haskell
|
||||
s = concat3 <$> string "a" <*> s <*> char "b"
|
||||
<|> string ""
|
||||
where
|
||||
concat3 x y z = x ++ y ++ z
|
||||
```
|
||||
|
22
parsec/_tmp/10_Introduction/020_intro-008.md
Normal file
22
parsec/_tmp/10_Introduction/020_intro-008.md
Normal file
|
@ -0,0 +1,22 @@
|
|||
## Applicative Style usefull with Data types
|
||||
|
||||
``` haskell
|
||||
data IP = IP Int Int Int Int
|
||||
|
||||
parseIP = IP <$>
|
||||
number <* char '.' <*>
|
||||
number <* char '.' <*>
|
||||
number <* char '.' <*>
|
||||
number
|
||||
|
||||
monadicParseIP = do
|
||||
d1 <- number
|
||||
char '.'
|
||||
d2 <- number
|
||||
char '.'
|
||||
d3 <- number
|
||||
char '.'
|
||||
d4 <- number
|
||||
return (IP d1 d2 d3 d4)
|
||||
```
|
||||
|
17
parsec/_tmp/10_Introduction/020_intro-009.md
Normal file
17
parsec/_tmp/10_Introduction/020_intro-009.md
Normal file
|
@ -0,0 +1,17 @@
|
|||
## Write number correctly
|
||||
|
||||
``` haskell
|
||||
number :: Parser Int
|
||||
number = do
|
||||
x <- read <$> many1 digit
|
||||
guard (0 <= x && x < 256) <?>
|
||||
"Number between 0 and 255 (here " ++ show x ++ ")"
|
||||
return (fromIntegral x)
|
||||
```
|
||||
|
||||
``` haskell
|
||||
>>> test parseIP "parseIP" "823.32.80.113"
|
||||
"parseIP" (line 1, column 4):
|
||||
unexpected "."
|
||||
expecting digit or Number between 0 and 255 (here 823)
|
||||
```
|
9
parsec/_tmp/10_Introduction/030_advanced-000.md
Normal file
9
parsec/_tmp/10_Introduction/030_advanced-000.md
Normal file
|
@ -0,0 +1,9 @@
|
|||
## So
|
||||
|
||||
- combination of simple parsers
|
||||
- error messages with `(<?>)`
|
||||
- embed result in data type using Applicative style
|
||||
- Not shown, use another monad with the parser
|
||||
|
||||
Time to do something cool
|
||||
|
4
parsec/_tmp/10_Introduction/030_advanced-001.md
Normal file
4
parsec/_tmp/10_Introduction/030_advanced-001.md
Normal file
|
@ -0,0 +1,4 @@
|
|||
## A Simple DSL
|
||||
|
||||
Let's write a minimal DSL
|
||||
|
14
parsec/_tmp/10_Introduction/030_advanced-002.md
Normal file
14
parsec/_tmp/10_Introduction/030_advanced-002.md
Normal file
|
@ -0,0 +1,14 @@
|
|||
## Useful definitions
|
||||
|
||||
`try` tries to parse and backtracks if it fails.
|
||||
|
||||
``` haskell
|
||||
(<||>) parser1 parser2 = try parser1 <|> parser2
|
||||
```
|
||||
|
||||
`lexeme`, just skip spaces.
|
||||
|
||||
``` haskell
|
||||
lexeme parser = whitespaces *> parser <* whitespaces
|
||||
```
|
||||
|
7
parsec/_tmp/10_Introduction/030_advanced-003.md
Normal file
7
parsec/_tmp/10_Introduction/030_advanced-003.md
Normal file
|
@ -0,0 +1,7 @@
|
|||
## Data Structure
|
||||
|
||||
Remember from text to data structure
|
||||
|
||||
``` haskell
|
||||
data Tree = Node Element [Tree]
|
||||
```
|
46
parsec/examples/03.hs
Normal file
46
parsec/examples/03.hs
Normal file
|
@ -0,0 +1,46 @@
|
|||
import Control.Applicative hiding (many, (<|>))
|
||||
import Text.Parsec
|
||||
import Data.Typeable
|
||||
|
||||
type Parser a = Parsec String () a
|
||||
|
||||
sa :: Parser String
|
||||
sa = concat3 <$> string "a" <*> sa <*> string "b" <|> string ""
|
||||
where
|
||||
concat3 x y z = x ++ y ++ z
|
||||
|
||||
s :: Parser String
|
||||
s = s' <|> epsilon
|
||||
|
||||
epsilon = string ""
|
||||
|
||||
s' :: Parser String
|
||||
s' = do
|
||||
a <- string "a"
|
||||
mid <- s
|
||||
b <- string "b"
|
||||
return (a ++ mid ++ b)
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
test s "S" "aaabbb"
|
||||
test s "S" "aabbb"
|
||||
test s "S" "aab"
|
||||
test s "S" ""
|
||||
test sa "S'" "aaabbb"
|
||||
test sa "S'" "aabbb"
|
||||
test sa "S'" "aab"
|
||||
test sa "S'" ""
|
||||
test parseIP "parseIP" "123.32.80.113"
|
||||
test parseIP "parseIP" "823.32.80.113"
|
||||
|
||||
test :: (Typeable a, Show a) => Parser a -> String -> String -> IO ()
|
||||
test parser description string = do
|
||||
putStrLn $ "-- " ++ description ++ " on '" ++ string ++ "'"
|
||||
let res = parse parser description string
|
||||
putStr $ show res
|
||||
case res of
|
||||
Left err -> return ()
|
||||
Right value -> putStr $ " :: " ++ show (typeOf value)
|
||||
putStrLn ""
|
||||
|
38
parsec/examples/parseIP.hs
Normal file
38
parsec/examples/parseIP.hs
Normal file
|
@ -0,0 +1,38 @@
|
|||
{-# LANGUAGE DeriveDataTypeable #-}
|
||||
import Control.Applicative hiding (many, (<|>))
|
||||
import Text.Parsec
|
||||
import Data.Typeable
|
||||
import Control.Monad (guard)
|
||||
|
||||
type Parser a = Parsec String () a
|
||||
|
||||
data IP = IP Int Int Int Int deriving (Show,Typeable)
|
||||
|
||||
parseIP :: Parser IP
|
||||
parseIP = IP <$>
|
||||
number <* char '.' <*>
|
||||
number <* char '.' <*>
|
||||
number <* char '.' <*>
|
||||
number
|
||||
|
||||
number :: Parser Int
|
||||
number = do
|
||||
x <- read <$> many1 digit
|
||||
guard (0 <= x && x < 256) <?> "Number between 0 and 255 (here " ++ show x ++ ")"
|
||||
return (fromIntegral x)
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
test parseIP "parseIP" "123.32.80.113"
|
||||
test parseIP "parseIP" "823.32.80.113"
|
||||
|
||||
test :: (Typeable a, Show a) => Parser a -> String -> String -> IO ()
|
||||
test parser description string = do
|
||||
putStrLn $ "-- " ++ description ++ " on '" ++ string ++ "'"
|
||||
let res = parse parser description string
|
||||
putStr $ show res
|
||||
case res of
|
||||
Left err -> return ()
|
||||
Right value -> putStr $ " :: " ++ show (typeOf value)
|
||||
putStrLn ""
|
||||
|
19
parsec/gen
19
parsec/gen
|
@ -10,14 +10,31 @@ fi
|
|||
cd $scriptdir
|
||||
|
||||
htmldir="_html"
|
||||
tmpdir="_tmp"
|
||||
[[ -e $htmldir ]] && \rm -rf $htmldir
|
||||
[[ -e $tmpdir ]] && \rm -rf $tmpdir
|
||||
mkdir -p $htmldir
|
||||
|
||||
# split a markdown file on ##
|
||||
splitMarkdown() {
|
||||
dstdir=$tmpdir/${1:h}
|
||||
mdfic=$tmpdir/${1:r}
|
||||
[[ ! -d $dstdir ]] && mkdir -p $dstdir
|
||||
awk '/^## /{ dest=sprintf("'$mdfic'-%03d.md",n); print dest; n++ } { print $0 > dest}' $1
|
||||
}
|
||||
|
||||
# Convert all slides from markdown
|
||||
for slide in **/*.{md,html}(.N); do
|
||||
dst="$htmldir/${slide:r}.html"
|
||||
[[ ! -e ${dst:h} ]] && mkdir -p ${dst:h}
|
||||
case ${slide:e} in
|
||||
md) pandoc -f markdown -t html $slide > $dst;;
|
||||
md) i=0
|
||||
for tmpfic in $(splitMarkdown $slide); do
|
||||
((i++))
|
||||
print "Split $tmpfic"
|
||||
dst="$( print -- ${tmpfic:r}.html | sed 's#'$tmpdir'#'$htmldir'#' )"
|
||||
pandoc -f markdown -t html $tmpfic > $dst
|
||||
done ;;
|
||||
html) cp $slide $dst;;
|
||||
esac
|
||||
done
|
||||
|
|
|
@ -1,55 +1,3 @@
|
|||
#!/usr/bin/env zsh
|
||||
|
||||
error(){print -- $* >&2; exit 1}
|
||||
|
||||
(($#<2)) && error "usage: ${0:t} [once] cmd dirs..."
|
||||
|
||||
ONCE=0
|
||||
[[ $1 = "once" ]] && { ONCE=1; shift }
|
||||
|
||||
(($#<2)) && error "usage: ${0:t} [once] cmd dirs..."
|
||||
|
||||
cmd="$1"
|
||||
shift
|
||||
|
||||
typeset -a listDir
|
||||
listDir=( $@ )
|
||||
|
||||
isRecentlyModified() {
|
||||
local fic="$1"
|
||||
local mtime=0
|
||||
currenttime=$(date +"%s")
|
||||
case $(uname) in
|
||||
Darwin) mtime=$(stat -f %m $fic);;
|
||||
Linux) mtime=$(stat --printf %Y $fic);;
|
||||
*) mtime=$(stat --printf %Y $fic);;
|
||||
esac
|
||||
(( $currenttime - $mtime < 2 ))
|
||||
}
|
||||
|
||||
checkfile=".last_watched"
|
||||
((ONCE == 0)) && \
|
||||
[[ -e $checkfile ]] && \
|
||||
isRecentlyModified $checkfile && \
|
||||
error "Wait at least 2 second if you killed the process"
|
||||
|
||||
execIfChanged() {
|
||||
isRecentlyModified $1 && { print -- "$cmd $1"; eval "$cmd $1"}
|
||||
}
|
||||
|
||||
typeset -A listFic
|
||||
while true; do
|
||||
listFic=()
|
||||
for d in $listDir; do
|
||||
if [[ -d $d ]]; then
|
||||
for fic in $d/**/*(.); do
|
||||
execIfChanged $fic
|
||||
done
|
||||
else
|
||||
execIfChanged $d
|
||||
fi
|
||||
done
|
||||
((ONCE == 1)) && break
|
||||
touch $checkfile
|
||||
sleep 2
|
||||
done
|
||||
./watch ./gen *.html 10_Introduction
|
||||
|
|
55
parsec/watch
Executable file
55
parsec/watch
Executable file
|
@ -0,0 +1,55 @@
|
|||
#!/usr/bin/env zsh
|
||||
|
||||
error(){print -- $* >&2; exit 1}
|
||||
|
||||
(($#<2)) && error "usage: ${0:t} [once] cmd dirs..."
|
||||
|
||||
ONCE=0
|
||||
[[ $1 = "once" ]] && { ONCE=1; shift }
|
||||
|
||||
(($#<2)) && error "usage: ${0:t} [once] cmd dirs..."
|
||||
|
||||
cmd="$1"
|
||||
shift
|
||||
|
||||
typeset -a listDir
|
||||
listDir=( $@ )
|
||||
|
||||
isRecentlyModified() {
|
||||
local fic="$1"
|
||||
local mtime=0
|
||||
currenttime=$(date +"%s")
|
||||
case $(uname) in
|
||||
Darwin) mtime=$(stat -f %m $fic);;
|
||||
Linux) mtime=$(stat --printf %Y $fic);;
|
||||
*) mtime=$(stat --printf %Y $fic);;
|
||||
esac
|
||||
(( $currenttime - $mtime < 2 ))
|
||||
}
|
||||
|
||||
checkfile=".last_watched"
|
||||
((ONCE == 0)) && \
|
||||
[[ -e $checkfile ]] && \
|
||||
isRecentlyModified $checkfile && \
|
||||
error "Wait at least 2 second if you killed the process"
|
||||
|
||||
execIfChanged() {
|
||||
isRecentlyModified $1 && { print -- "$cmd $1"; eval "$cmd $1"}
|
||||
}
|
||||
|
||||
typeset -A listFic
|
||||
while true; do
|
||||
listFic=()
|
||||
for d in $listDir; do
|
||||
if [[ -d $d ]]; then
|
||||
for fic in $d/**/*(.); do
|
||||
execIfChanged $fic
|
||||
done
|
||||
else
|
||||
execIfChanged $d
|
||||
fi
|
||||
done
|
||||
((ONCE == 1)) && break
|
||||
touch $checkfile
|
||||
sleep 2
|
||||
done
|
Loading…
Reference in a new issue