我试图使用解析器组合器来解决问题。我尝试了以下方法:
注意:以下代码使用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) )
我很难理解这个解析器是如何运行的,因为在解析器成功之前调用了styleParserItalic
解析器。
有人可以解释解析器在给出一串字符时的工作原理吗?
如果某人对解析器的目的和完整代码感兴趣,here是我之前的问题。
这是我迄今所理解的
解析器将首先检查它是否是一行的结尾,如果不是,它将尝试解析字符串(!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]
答案 0 :(得分:3)
解析器组合器(通常)在成功时消耗输入。在此库中,如果string "(!ITALIC!)"
失败,则不会消耗任何输入。由于使用了<|>
组合子,因此它会尝试使用以anyChar
开头的代码的下一部分。
当anyChar
成功时,它会消耗该单个字符,并在c
后andThen
内捕获该字符。然后,当对anyChar
进行递归调用时,剩余的字符串(除styleParserItalic bolded
捕获的字符之外的所有字符串)都会被“爬行”。第二个andThen
将递归组合子的输出捕获到cs
,并将捕获的字符预先添加到递归调用的其余字符列表中。
我认为要记住的重要部分是组合器在成功时消耗输入,并且(通常)在输入失败时不消耗输入。
答案 1 :(得分:2)
首先是一些简单的......
(1)签名中内部列表的每个元素:
svg-slide
只是一个字符。只需从最后一行删除active
,
styleParserItalic : Bool -> Parser ( List (List Char , Style))
^^^^^^^^^
你可以让它有这个签名。
(2)请注意,:: []
参数仅影响样式 - 它对控制流没有影响。它应该被称为 <|> ... `andThen` \cs -> succeed ((c ,style) :: cs) )
^^^
removed `:: []`
,因为如果参数为True,输出中显示的样式为bolded
,否则为italic
。
另请注意,一旦此参数设置为True,它将保持为True 所有后续的递归调用。
所以现在算法是:
Italic
,请在解析的其余部分使用Unstyled
作为样式。近似Python算法类似于:
(!ITALIC!)