I was trying to solve a problem using a parser combinator. I tried the following:
Note: the below code uses the combinator library
styleParserItalic : Bool -> Parser ( List (List Char , Style))
styleParserItalic bolded =
let
style = if bolded then Italic else Unstyled
in
(end `andThen` always ( succeed ( [] )))
<|> (string "(!ITALIC!)" `andThen` \_ -> styleParserItalic ( not bolded ) )
<|> ( anyChar `andThen` \c -> styleParserItalic bolded `andThen` \cs -> succeed ((c :: [],style) :: cs) )
I am struggling to understand how this parser runs since the styleParserItalic
parser is called before the parser succeeds.
Could someone explain how the parser works when it is given a string of characters?
If someone is interested in the purpose of the parser and the full code, here is my previous question.
Here is what I have understood thus far
The parser will check first if it is the end of a line , if not it will try to parser the string (!ITALIC!)
if that the case then it will call the parser with with parameter True or false (if false then will makes it true ..)
If the parser does not find the the string (!ITALIC!) it will try to parse any character then it will call the parser again.
What confuses me is that the parser will keep calling itself as long as it succeeds with parsing any character!
edit :* NOTE THE BELOW IS NOT A PART OF THE QUESTION, JUST TO SHARE THE CODE IF SOMEONE IS INTERESTED
thanks for all responses, I have updated the parser to parse Bold italic underline..., as per the below screen shot
type Style = Bold| Unstyled | Italic | Coded | Lined | Titled | Marked | Underline
styleParser : Bool ->Bool ->Bool ->Bool-> Bool-> Bool->Bool
-> Parser ( List (List Char , (Style,Style,Style,Style,Style,Style,Style)))
--(bold,italic ,code,line ,Titled,mark)
styleParser bolded italiced coded lined titled marked underlined=
let
style = (
if bolded then Bold else Unstyled
,if italiced then Italic else Unstyled
,if coded then Coded else Unstyled
,if lined then Lined else Unstyled
,if titled then Titled else Unstyled
,if marked then Marked else Unstyled
,if underlined then Underline else Unstyled
)
in
(end `andThen` always ( succeed ( [] )))
<|> (string "//" `andThen` \_ -> styleParser bolded italiced coded lined titled marked (not underlined))
<|> (string "**" `andThen` \_ -> styleParser (not bolded) italiced coded lined titled marked underlined)
<|> (string "*" `andThen` \_ -> styleParser bolded (not italiced) coded lined titled marked underlined)
<|> (string "`" `andThen` \_ -> styleParser bolded italiced (not coded) lined titled marked underlined)
<|> (string "/br" `andThen` \_ -> styleParser bolded italiced coded (not lined) titled marked underlined)
<|> (string "/*" `andThen` \_ -> styleParser bolded italiced coded lined (not titled) marked underlined)
<|> (string "{-" `andThen` \_ -> styleParser bolded italiced coded lined titled (not marked) underlined)
<|> ( anyChar `andThen` \c -> styleParser bolded italiced coded lined titled marked underlined `andThen` \cs -> succeed ((c :: [],style) :: cs) )
foldStyleHtml : List ( List Char , ( Style,Style,Style,Style,Style,Style,Style) ) -> List (Html Msg)
foldStyleHtml lst =
List.map styleToHtml lst
styleToHtml : ( List Char, (Style ,Style,Style,Style,Style,Style,Style)) -> Html Msg
styleToHtml (a,b) =
case b of
(Bold,Italic,_,_,_,_,Unstyled) -> strong [] [em [][ text (String.fromList a)]]
(Bold,Italic,_,_,_,_,Underline) -> u[][ strong [] [em [][ text (String.fromList a)]]]
(Bold,Unstyled,_,_,_,_,Underline) -> u[][ strong [] [text (String.fromList a)]]
(Unstyled,Italic,_,_,_,_,Underline) -> u[][ em [] [text (String.fromList a)]]
(Unstyled,Italic,_,_,_,_,_) -> em[] [text (String.fromList a)]
(Bold,Unstyled,_,_,_,_,_) -> strong [][ text (String.fromList a)]
(_,_,Coded,_,_,_,_) -> code [codeStyle ][text (String.fromList a)]
(_,_,_,Lined,_,_,_) -> br [][text " "]
-- (_,_,_,_,Titled,_,_) -> div [][text (String.fromList a)]
(_,_,_,_,_,Marked,_) -> mark [][text (String.fromList a)]
(_,_,_,_,_,_,Underline) -> u [][text (String.fromList a)]
(_,_,_,_,_,_,_) -> text (String.fromList a)
htmlParser : Parser (List (Html Msg))
htmlParser =
styleParser False False False False False False False `andThen` (succeed << foldStyleHtml )
runParser : Parser (List (Html Msg)) -> String -> Html Msg
runParser parser str =
case parse parser str of
(Ok htmls,_)-> div [] htmls
(Err err, _) -> div [ style [("color", "red")] ] [ text <| toString <| err]
Parser combinators (generally) consume input as they succeed. In this library, if string "(!ITALIC!)"
fails, it will not consume any input. Since the <|>
combinator is used, it then tries to use the next part of the code that starts with anyChar
.
When anyChar
succeeds, it consumes that single character and captures it in c
after andThen
. Then the remaining string (everything but the character captured by anyChar
) is then "crawled" when the recursive call to styleParserItalic bolded
is made. That second andThen
captures the output of the recursive combinator into cs
and prepends the captured character onto the rest of the list of characters from the recursive call.
I think the important part to remember is that the combinators consume input as they succeed and (generally) don't consume input when they fail.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With