我试图使用解析器组合器来解决问题.我尝试了以下方法:
注意:以下代码使用组合子库
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) )
Run Code Online (Sandbox Code Playgroud)
我很难理解这个解析器是如何运行的,因为styleParserItalic在解析器成功之前调用解析器.
有人可以解释解析器在给出一串字符时是如何工作的吗?
如果有人对解析器的目的和完整代码感兴趣,这是我之前的问题.
这是迄今为止我所理解的
解析器将首先检查它是否是行的结尾,如果不是,它将尝试解析字符串,(!ITALIC!)如果情况那么它将使用参数True或false调用解析器(如果为false则将使其为真...)
如果解析器没有找到字符串(!ITALIC!),它将尝试解析任何字符,然后它将再次调用解析器.
令我困惑的是,解析器只要成功解析任何字符就会继续调用自己!
编辑:* 注意以下不是问题的一部分,如果有人有兴趣的话,只需分享代码
感谢所有回复,我更新了解析器以解析粗体斜体下划线...,如下面的屏幕截图所示
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]
Run Code Online (Sandbox Code Playgroud)
解析器组合器(通常)在成功时消耗输入。在这个库中,如果string "(!ITALIC!)"失败,它不会消耗任何输入。由于<|>使用了组合器,因此它会尝试使用以 开头的代码的下一部分anyChar。
当成功时,它会消耗该单个字符并在afteranyChar中捕获它。然后,当进行递归调用时,剩余的字符串(除了 捕获的字符之外的所有内容)都会被“爬行” 。这一秒将递归组合器的输出捕获到递归调用中,并将捕获的字符添加到其余字符列表中。candThenanyCharstyleParserItalic boldedandThencs
我认为要记住的重要部分是,组合器在成功时消耗输入,并且(通常)在失败时不消耗输入。
| 归档时间: |
|
| 查看次数: |
359 次 |
| 最近记录: |